diff options
255 files changed, 7685 insertions, 41249 deletions
diff --git a/context/data/scite/lexers/data/scite-context-data-context.lua b/context/data/scite/lexers/data/scite-context-data-context.lua index 0d577c8da..f167c82c1 100644 --- a/context/data/scite/lexers/data/scite-context-data-context.lua +++ b/context/data/scite/lexers/data/scite-context-data-context.lua @@ -1,4 +1,4 @@ return { ["constants"]={ "zerocount", "minusone", "minustwo", "plusone", "plustwo", "plusthree", "plusfour", "plusfive", "plussix", "plusseven", "pluseight", "plusnine", "plusten", "plussixteen", "plushundred", "plusthousand", "plustenthousand", "plustwentythousand", "medcard", "maxcard", "zeropoint", "onepoint", "halfapoint", "onebasepoint", "maxdimen", "scaledpoint", "thousandpoint", "points", "halfpoint", "zeroskip", "zeromuskip", "onemuskip", "pluscxxvii", "pluscxxviii", "pluscclv", "pluscclvi", "normalpagebox", "endoflinetoken", "outputnewlinechar", "emptytoks", "empty", "undefined", "voidbox", "emptybox", "emptyvbox", "emptyhbox", "bigskipamount", "medskipamount", "smallskipamount", "fmtname", "fmtversion", "texengine", "texenginename", "texengineversion", "luatexengine", "pdftexengine", "xetexengine", "unknownengine", "etexversion", "pdftexversion", "xetexversion", "xetexrevision", "activecatcode", "bgroup", "egroup", "endline", "conditionaltrue", "conditionalfalse", "attributeunsetvalue", "uprotationangle", "rightrotationangle", "downrotationangle", "leftrotationangle", "inicatcodes", "ctxcatcodes", "texcatcodes", "notcatcodes", "txtcatcodes", "vrbcatcodes", "prtcatcodes", "nilcatcodes", "luacatcodes", "tpacatcodes", "tpbcatcodes", "xmlcatcodes", "escapecatcode", "begingroupcatcode", "endgroupcatcode", "mathshiftcatcode", "alignmentcatcode", "endoflinecatcode", "parametercatcode", "superscriptcatcode", "subscriptcatcode", "ignorecatcode", "spacecatcode", "lettercatcode", "othercatcode", "activecatcode", "commentcatcode", "invalidcatcode", "tabasciicode", "newlineasciicode", "formfeedasciicode", "endoflineasciicode", "endoffileasciicode", "spaceasciicode", "hashasciicode", "dollarasciicode", "commentasciicode", "ampersandasciicode", "colonasciicode", "backslashasciicode", "circumflexasciicode", "underscoreasciicode", "leftbraceasciicode", "barasciicode", "rightbraceasciicode", "tildeasciicode", "delasciicode", "lessthanasciicode", "morethanasciicode", "doublecommentsignal", "atsignasciicode", "exclamationmarkasciicode", "questionmarkasciicode", "doublequoteasciicode", "singlequoteasciicode", "forwardslashasciicode", "primeasciicode", "activemathcharcode", "activetabtoken", "activeformfeedtoken", "activeendoflinetoken", "batchmodecode", "nonstopmodecode", "scrollmodecode", "errorstopmodecode", "bottomlevelgroupcode", "simplegroupcode", "hboxgroupcode", "adjustedhboxgroupcode", "vboxgroupcode", "vtopgroupcode", "aligngroupcode", "noaligngroupcode", "outputgroupcode", "mathgroupcode", "discretionarygroupcode", "insertgroupcode", "vcentergroupcode", "mathchoicegroupcode", "semisimplegroupcode", "mathshiftgroupcode", "mathleftgroupcode", "vadjustgroupcode", "charnodecode", "hlistnodecode", "vlistnodecode", "rulenodecode", "insertnodecode", "marknodecode", "adjustnodecode", "ligaturenodecode", "discretionarynodecode", "whatsitnodecode", "mathnodecode", "gluenodecode", "kernnodecode", "penaltynodecode", "unsetnodecode", "mathsnodecode", "charifcode", "catifcode", "numifcode", "dimifcode", "oddifcode", "vmodeifcode", "hmodeifcode", "mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode", "trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode", "fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink", "fontexheight", "fontemwidth", "fontextraspace", "slantperpoint", "interwordspace", "interwordstretch", "interwordshrink", "exheight", "emwidth", "extraspace", "mathsupdisplay", "mathsupnormal", "mathsupcramped", "mathsubnormal", "mathsubcombined", "mathaxisheight", "startmode", "stopmode", "startnotmode", "stopnotmode", "startmodeset", "stopmodeset", "doifmode", "doifmodeelse", "doifnotmode", "startallmodes", "stopallmodes", "startnotallmodes", "stopnotallmodes", "doifallmodes", "doifallmodeselse", "doifnotallmodes", "startenvironment", "stopenvironment", "environment", "startcomponent", "stopcomponent", "component", "startproduct", "stopproduct", "product", "startproject", "stopproject", "project", "starttext", "stoptext", "startnotext", "stopnotext", "startdocument", "stopdocument", "documentvariable", "setupdocument", "startmodule", "stopmodule", "usemodule", "usetexmodule", "useluamodule", "setupmodule", "currentmoduleparameter", "moduleparameter", "startTEXpage", "stopTEXpage", "enablemode", "disablemode", "preventmode", "globalenablemode", "globaldisablemode", "globalpreventmode", "pushmode", "popmode", "typescriptone", "typescripttwo", "typescriptthree", "mathsizesuffix", "mathordcode", "mathopcode", "mathbincode", "mathrelcode", "mathopencode", "mathclosecode", "mathpunctcode", "mathalphacode", "mathinnercode", "mathnothingcode", "mathlimopcode", "mathnolopcode", "mathboxcode", "mathchoicecode", "mathaccentcode", "mathradicalcode", "constantnumber", "constantnumberargument", "constantdimen", "constantdimenargument", "constantemptyargument", "continueifinputfile", "luastringsep", "!!bs", "!!es", "lefttorightmark", "righttoleftmark", "breakablethinspace", "nobreakspace", "narrownobreakspace", "zerowidthnobreakspace", "ideographicspace", "ideographichalffillspace", "twoperemspace", "threeperemspace", "fourperemspace", "fiveperemspace", "sixperemspace", "figurespace", "punctuationspace", "hairspace", "zerowidthspace", "zerowidthnonjoiner", "zerowidthjoiner", "zwnj", "zwj" }, - ["helpers"]={ "startsetups", "stopsetups", "startxmlsetups", "stopxmlsetups", "startluasetups", "stopluasetups", "starttexsetups", "stoptexsetups", "startrawsetups", "stoprawsetups", "startlocalsetups", "stoplocalsetups", "starttexdefinition", "stoptexdefinition", "starttexcode", "stoptexcode", "startcontextcode", "stopcontextcode", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "doifelsecommandhandler", "doifnotcommandhandler", "doifcommandhandler", "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", "booleanmodevalue", "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif", "newlanguage", "newfamily", "newfam", "newhelp", "then", "begcsname", "strippedcsname", "firstargumentfalse", "firstargumenttrue", "secondargumentfalse", "secondargumenttrue", "thirdargumentfalse", "thirdargumenttrue", "fourthargumentfalse", "fourthargumenttrue", "fifthargumentfalse", "fifthsargumenttrue", "sixthargumentfalse", "sixtsargumenttrue", "doglobal", "dodoglobal", "redoglobal", "resetglobal", "donothing", "dontcomplain", "forgetall", "donetrue", "donefalse", "htdp", "unvoidbox", "hfilll", "vfilll", "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha", "currentcatcodetable", "defaultcatcodetable", "catcodetablename", "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable", "pushcatcodetable", "popcatcodetable", "restorecatcodes", "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand", "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg", "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledmbox", "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern", "ruledhglue", "ruledvglue", "normalhglue", "normalvglue", "ruledpenalty", "filledhboxb", "filledhboxr", "filledhboxg", "filledhboxc", "filledhboxm", "filledhboxy", "filledhboxk", "scratchcounter", "globalscratchcounter", "scratchdimen", "globalscratchdimen", "scratchskip", "globalscratchskip", "scratchmuskip", "globalscratchmuskip", "scratchtoks", "globalscratchtoks", "scratchbox", "globalscratchbox", "normalbaselineskip", "normallineskip", "normallineskiplimit", "availablehsize", "localhsize", "setlocalhsize", "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset", "scratchxposition", "scratchyposition", "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset", "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", "scratchnx", "scratchny", "scratchmx", "scratchmy", "scratchunicode", "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip", "doif", "doifnot", "doifelse", "doifinset", "doifnotinset", "doifinsetelse", "doifnextcharelse", "doifnextoptionalelse", "doifnextbgroupelse", "doifnextparenthesiselse", "doiffastoptionalcheckelse", "doifundefinedelse", "doifdefinedelse", "doifundefined", "doifdefined", "doifelsevalue", "doifvalue", "doifnotvalue", "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse", "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing", "doifdimensionelse", "doifnumberelse", "doifnumber", "doifnotnumber", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", "doifassignmentelse", "docheckassignment", "tracingall", "tracingnone", "loggingall", "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "obeyedspace", "obeyedline", "normalspace", "executeifdefined", "singleexpandafter", "doubleexpandafter", "tripleexpandafter", "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces", "wait", "writestatus", "define", "defineexpandable", "redefine", "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure", "measured", "installcorenamespace", "getvalue", "getuvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", "globallet", "glet", "udef", "ugdef", "uedef", "uxdef", "checked", "unique", "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter", "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter", "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist", "processaction", "processallactions", "processfirstactioninset", "processallactionsinset", "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect", "firstofoneargument", "firstoftwoarguments", "secondoftwoarguments", "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments", "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments", "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments", "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments", "firstofoneunexpanded", "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments", "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals", "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "dowith", "newconstant", "setnewconstant", "setconstant", "setconstantvalue", "newconditional", "settrue", "setfalse", "settruevalue", "setfalsevalue", "newmacro", "setnewmacro", "newfraction", "newsignal", "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "permitspacesbetweengroups", "dontpermitspacesbetweengroups", "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "modulonumber", "dividenumber", "getfirstcharacter", "doiffirstcharelse", "startnointerference", "stopnointerference", "twodigits", "threedigits", "leftorright", "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight", "ordordspacing", "ordopspacing", "ordbinspacing", "ordrelspacing", "ordopenspacing", "ordclosespacing", "ordpunctspacing", "ordinnerspacing", "opordspacing", "opopspacing", "opbinspacing", "oprelspacing", "opopenspacing", "opclosespacing", "oppunctspacing", "opinnerspacing", "binordspacing", "binopspacing", "binbinspacing", "binrelspacing", "binopenspacing", "binclosespacing", "binpunctspacing", "bininnerspacing", "relordspacing", "relopspacing", "relbinspacing", "relrelspacing", "relopenspacing", "relclosespacing", "relpunctspacing", "relinnerspacing", "openordspacing", "openopspacing", "openbinspacing", "openrelspacing", "openopenspacing", "openclosespacing", "openpunctspacing", "openinnerspacing", "closeordspacing", "closeopspacing", "closebinspacing", "closerelspacing", "closeopenspacing", "closeclosespacing", "closepunctspacing", "closeinnerspacing", "punctordspacing", "punctopspacing", "punctbinspacing", "punctrelspacing", "punctopenspacing", "punctclosespacing", "punctpunctspacing", "punctinnerspacing", "innerordspacing", "inneropspacing", "innerbinspacing", "innerrelspacing", "inneropenspacing", "innerclosespacing", "innerpunctspacing", "innerinnerspacing", "normalreqno", "startimath", "stopimath", "normalstartimath", "normalstopimath", "startdmath", "stopdmath", "normalstartdmath", "normalstopdmath", "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathsmallstylefont", "mathstyleface", "mathsmallstyleface", "mathstylecommand", "mathpalette", "mathstylehbox", "mathstylevbox", "mathstylevcenter", "mathstylevcenteredhbox", "mathstylevcenteredvbox", "mathtext", "setmathsmalltextbox", "setmathtextbox", "triggerdisplaystyle", "triggertextstyle", "triggerscriptstyle", "triggerscriptscriptstyle", "triggeruncrampedstyle", "triggercrampedstyle", "triggersmallstyle", "triggeruncrampedsmallstyle", "triggercrampedsmallstyle", "triggerbigstyle", "triggeruncrampedbigstyle", "triggercrampedbigstyle", "luaexpr", "expdoifelse", "expdoif", "expdoifnot", "expdoifcommonelse", "expdoifinsetelse", "ctxdirectlua", "ctxlatelua", "ctxsprint", "ctxwrite", "ctxcommand", "ctxdirectcommand", "ctxlatecommand", "ctxreport", "ctxlua", "luacode", "lateluacode", "directluacode", "registerctxluafile", "ctxloadluafile", "luaversion", "luamajorversion", "luaminorversion", "ctxluacode", "luaconditional", "luaexpanded", "startluaparameterset", "stopluaparameterset", "luaparameterset", "definenamedlua", "obeylualines", "obeyluatokens", "startluacode", "stopluacode", "startlua", "stoplua", "carryoverpar", "assumelongusagecs", "Umathbotaccent", "righttolefthbox", "lefttorighthbox", "righttoleftvbox", "lefttorightvbox", "righttoleftvtop", "lefttorightvtop", "rtlhbox", "ltrhbox", "rtlvbox", "ltrvbox", "rtlvtop", "ltrvtop", "autodirhbox", "autodirvbox", "autodirvtop", "lefttoright", "righttoleft", "synchronizelayoutdirection", "synchronizedisplaydirection", "synchronizeinlinedirection", "lesshyphens", "morehyphens", "nohyphens", "dohyphens", "Ucheckedstartdisplaymath", "Ucheckedstopdisplaymath" }, + ["helpers"]={ "startsetups", "stopsetups", "startxmlsetups", "stopxmlsetups", "startluasetups", "stopluasetups", "starttexsetups", "stoptexsetups", "startrawsetups", "stoprawsetups", "startlocalsetups", "stoplocalsetups", "starttexdefinition", "stoptexdefinition", "starttexcode", "stoptexcode", "startcontextcode", "stopcontextcode", "doifsetupselse", "doifsetups", "doifnotsetups", "setup", "setups", "texsetup", "xmlsetup", "luasetup", "directsetup", "doifelsecommandhandler", "doifnotcommandhandler", "doifcommandhandler", "newmode", "setmode", "resetmode", "newsystemmode", "setsystemmode", "resetsystemmode", "pushsystemmode", "popsystemmode", "booleanmodevalue", "newcount", "newdimen", "newskip", "newmuskip", "newbox", "newtoks", "newread", "newwrite", "newmarks", "newinsert", "newattribute", "newif", "newlanguage", "newfamily", "newfam", "newhelp", "then", "begcsname", "strippedcsname", "firstargumentfalse", "firstargumenttrue", "secondargumentfalse", "secondargumenttrue", "thirdargumentfalse", "thirdargumenttrue", "fourthargumentfalse", "fourthargumenttrue", "fifthargumentfalse", "fifthsargumenttrue", "sixthargumentfalse", "sixtsargumenttrue", "doglobal", "dodoglobal", "redoglobal", "resetglobal", "donothing", "dontcomplain", "forgetall", "donetrue", "donefalse", "htdp", "unvoidbox", "hfilll", "vfilll", "mathbox", "mathlimop", "mathnolop", "mathnothing", "mathalpha", "currentcatcodetable", "defaultcatcodetable", "catcodetablename", "newcatcodetable", "startcatcodetable", "stopcatcodetable", "startextendcatcodetable", "stopextendcatcodetable", "pushcatcodetable", "popcatcodetable", "restorecatcodes", "setcatcodetable", "letcatcodecommand", "defcatcodecommand", "uedcatcodecommand", "hglue", "vglue", "hfillneg", "vfillneg", "hfilllneg", "vfilllneg", "ruledhss", "ruledhfil", "ruledhfill", "ruledhfilneg", "ruledhfillneg", "normalhfillneg", "ruledvss", "ruledvfil", "ruledvfill", "ruledvfilneg", "ruledvfillneg", "normalvfillneg", "ruledhbox", "ruledvbox", "ruledvtop", "ruledvcenter", "ruledmbox", "ruledhskip", "ruledvskip", "ruledkern", "ruledmskip", "ruledmkern", "ruledhglue", "ruledvglue", "normalhglue", "normalvglue", "ruledpenalty", "filledhboxb", "filledhboxr", "filledhboxg", "filledhboxc", "filledhboxm", "filledhboxy", "filledhboxk", "scratchcounter", "globalscratchcounter", "scratchdimen", "globalscratchdimen", "scratchskip", "globalscratchskip", "scratchmuskip", "globalscratchmuskip", "scratchtoks", "globalscratchtoks", "scratchbox", "globalscratchbox", "normalbaselineskip", "normallineskip", "normallineskiplimit", "availablehsize", "localhsize", "setlocalhsize", "nextbox", "dowithnextbox", "dowithnextboxcs", "dowithnextboxcontent", "dowithnextboxcontentcs", "scratchwidth", "scratchheight", "scratchdepth", "scratchoffset", "scratchdistance", "scratchhsize", "scratchvsize", "scratchxoffset", "scratchyoffset", "scratchhoffset", "scratchvoffset", "scratchxposition", "scratchyposition", "scratchtopoffset", "scratchbottomoffset", "scratchleftoffset", "scratchrightoffset", "scratchcounterone", "scratchcountertwo", "scratchcounterthree", "scratchdimenone", "scratchdimentwo", "scratchdimenthree", "scratchskipone", "scratchskiptwo", "scratchskipthree", "scratchmuskipone", "scratchmuskiptwo", "scratchmuskipthree", "scratchtoksone", "scratchtokstwo", "scratchtoksthree", "scratchboxone", "scratchboxtwo", "scratchboxthree", "scratchnx", "scratchny", "scratchmx", "scratchmy", "scratchunicode", "scratchleftskip", "scratchrightskip", "scratchtopskip", "scratchbottomskip", "doif", "doifnot", "doifelse", "doifinset", "doifnotinset", "doifinsetelse", "doifnextcharelse", "doifnextoptionalelse", "doifnextbgroupelse", "doifnextparenthesiselse", "doiffastoptionalcheckelse", "doifundefinedelse", "doifdefinedelse", "doifundefined", "doifdefined", "doifelsevalue", "doifvalue", "doifnotvalue", "doifnothing", "doifsomething", "doifelsenothing", "doifsomethingelse", "doifvaluenothing", "doifvaluesomething", "doifelsevaluenothing", "doifdimensionelse", "doifnumberelse", "doifnumber", "doifnotnumber", "doifcommonelse", "doifcommon", "doifnotcommon", "doifinstring", "doifnotinstring", "doifinstringelse", "doifassignmentelse", "docheckassignment", "tracingall", "tracingnone", "loggingall", "removetoks", "appendtoks", "prependtoks", "appendtotoks", "prependtotoks", "to", "endgraf", "endpar", "everyendpar", "reseteverypar", "finishpar", "empty", "null", "space", "quad", "enspace", "obeyspaces", "obeylines", "obeyedspace", "obeyedline", "normalspace", "executeifdefined", "singleexpandafter", "doubleexpandafter", "tripleexpandafter", "dontleavehmode", "removelastspace", "removeunwantedspaces", "keepunwantedspaces", "wait", "writestatus", "define", "defineexpandable", "redefine", "setmeasure", "setemeasure", "setgmeasure", "setxmeasure", "definemeasure", "freezemeasure", "measure", "measured", "installcorenamespace", "getvalue", "getuvalue", "setvalue", "setevalue", "setgvalue", "setxvalue", "letvalue", "letgvalue", "resetvalue", "undefinevalue", "ignorevalue", "setuvalue", "setuevalue", "setugvalue", "setuxvalue", "globallet", "glet", "udef", "ugdef", "uedef", "uxdef", "checked", "unique", "getparameters", "geteparameters", "getgparameters", "getxparameters", "forgetparameters", "copyparameters", "getdummyparameters", "dummyparameter", "directdummyparameter", "setdummyparameter", "letdummyparameter", "usedummystyleandcolor", "usedummystyleparameter", "usedummycolorparameter", "processcommalist", "processcommacommand", "quitcommalist", "quitprevcommalist", "processaction", "processallactions", "processfirstactioninset", "processallactionsinset", "unexpanded", "expanded", "startexpanded", "stopexpanded", "protected", "protect", "unprotect", "firstofoneargument", "firstoftwoarguments", "secondoftwoarguments", "firstofthreearguments", "secondofthreearguments", "thirdofthreearguments", "firstoffourarguments", "secondoffourarguments", "thirdoffourarguments", "fourthoffourarguments", "firstoffivearguments", "secondoffivearguments", "thirdoffivearguments", "fourthoffivearguments", "fifthoffivearguments", "firstofsixarguments", "secondofsixarguments", "thirdofsixarguments", "fourthofsixarguments", "fifthofsixarguments", "sixthofsixarguments", "firstofoneunexpanded", "gobbleoneargument", "gobbletwoarguments", "gobblethreearguments", "gobblefourarguments", "gobblefivearguments", "gobblesixarguments", "gobblesevenarguments", "gobbleeightarguments", "gobbleninearguments", "gobbletenarguments", "gobbleoneoptional", "gobbletwooptionals", "gobblethreeoptionals", "gobblefouroptionals", "gobblefiveoptionals", "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "dowith", "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant", "newmacro", "setnewmacro", "newfraction", "newsignal", "dosingleempty", "dodoubleempty", "dotripleempty", "doquadrupleempty", "doquintupleempty", "dosixtupleempty", "doseventupleempty", "dosingleargument", "dodoubleargument", "dotripleargument", "doquadrupleargument", "doquintupleargument", "dosixtupleargument", "doseventupleargument", "dosinglegroupempty", "dodoublegroupempty", "dotriplegroupempty", "doquadruplegroupempty", "doquintuplegroupempty", "permitspacesbetweengroups", "dontpermitspacesbetweengroups", "nopdfcompression", "maximumpdfcompression", "normalpdfcompression", "modulonumber", "dividenumber", "getfirstcharacter", "doiffirstcharelse", "startnointerference", "stopnointerference", "twodigits", "threedigits", "leftorright", "strut", "setstrut", "strutbox", "strutht", "strutdp", "strutwd", "struthtdp", "begstrut", "endstrut", "lineheight", "ordordspacing", "ordopspacing", "ordbinspacing", "ordrelspacing", "ordopenspacing", "ordclosespacing", "ordpunctspacing", "ordinnerspacing", "opordspacing", "opopspacing", "opbinspacing", "oprelspacing", "opopenspacing", "opclosespacing", "oppunctspacing", "opinnerspacing", "binordspacing", "binopspacing", "binbinspacing", "binrelspacing", "binopenspacing", "binclosespacing", "binpunctspacing", "bininnerspacing", "relordspacing", "relopspacing", "relbinspacing", "relrelspacing", "relopenspacing", "relclosespacing", "relpunctspacing", "relinnerspacing", "openordspacing", "openopspacing", "openbinspacing", "openrelspacing", "openopenspacing", "openclosespacing", "openpunctspacing", "openinnerspacing", "closeordspacing", "closeopspacing", "closebinspacing", "closerelspacing", "closeopenspacing", "closeclosespacing", "closepunctspacing", "closeinnerspacing", "punctordspacing", "punctopspacing", "punctbinspacing", "punctrelspacing", "punctopenspacing", "punctclosespacing", "punctpunctspacing", "punctinnerspacing", "innerordspacing", "inneropspacing", "innerbinspacing", "innerrelspacing", "inneropenspacing", "innerclosespacing", "innerpunctspacing", "innerinnerspacing", "normalreqno", "startimath", "stopimath", "normalstartimath", "normalstopimath", "startdmath", "stopdmath", "normalstartdmath", "normalstopdmath", "uncramped", "cramped", "triggermathstyle", "mathstylefont", "mathsmallstylefont", "mathstyleface", "mathsmallstyleface", "mathstylecommand", "mathpalette", "mathstylehbox", "mathstylevbox", "mathstylevcenter", "mathstylevcenteredhbox", "mathstylevcenteredvbox", "mathtext", "setmathsmalltextbox", "setmathtextbox", "triggerdisplaystyle", "triggertextstyle", "triggerscriptstyle", "triggerscriptscriptstyle", "triggeruncrampedstyle", "triggercrampedstyle", "triggersmallstyle", "triggeruncrampedsmallstyle", "triggercrampedsmallstyle", "triggerbigstyle", "triggeruncrampedbigstyle", "triggercrampedbigstyle", "luaexpr", "expdoifelse", "expdoif", "expdoifnot", "expdoifcommonelse", "expdoifinsetelse", "ctxdirectlua", "ctxlatelua", "ctxsprint", "ctxwrite", "ctxcommand", "ctxdirectcommand", "ctxlatecommand", "ctxreport", "ctxlua", "luacode", "lateluacode", "directluacode", "registerctxluafile", "ctxloadluafile", "luaversion", "luamajorversion", "luaminorversion", "ctxluacode", "luaconditional", "luaexpanded", "startluaparameterset", "stopluaparameterset", "luaparameterset", "definenamedlua", "obeylualines", "obeyluatokens", "startluacode", "stopluacode", "startlua", "stoplua", "carryoverpar", "assumelongusagecs", "Umathbotaccent", "righttolefthbox", "lefttorighthbox", "righttoleftvbox", "lefttorightvbox", "righttoleftvtop", "lefttorightvtop", "rtlhbox", "ltrhbox", "rtlvbox", "ltrvbox", "rtlvtop", "ltrvtop", "autodirhbox", "autodirvbox", "autodirvtop", "lefttoright", "righttoleft", "synchronizelayoutdirection", "synchronizedisplaydirection", "synchronizeinlinedirection", "lesshyphens", "morehyphens", "nohyphens", "dohyphens" }, }
\ No newline at end of file diff --git a/context/data/scite/lexers/data/scite-context-data-metafun.lua b/context/data/scite/lexers/data/scite-context-data-metafun.lua index 50b9ecec4..1ca02de97 100644 --- a/context/data/scite/lexers/data/scite-context-data-metafun.lua +++ b/context/data/scite/lexers/data/scite-context-data-metafun.lua @@ -1,4 +1,4 @@ return { - ["commands"]={ "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "invtan", "acosh", "asinh", "sinh", "cosh", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "smoothed", "cornered", "superellipsed", "randomized", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withlinearshading", "withcircularshading", "withfromshadecolor", "withtoshadecolor", "withshading", "shadedinto", "withcircularshade", "withlinearshade", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "graphictext", "loadfigure", "externalfigure", "withmask", "figure", "register", "bitmapimage", "colordecimals", "ddecimal", "dddecimal", "ddddecimal", "textext", "thetextext", "rawtextext", "textextoffset", "verbatim", "thelabel", "label", "autoalign", "transparent", "withtransparency", "property", "properties", "withproperties", "asgroup", "infont", "set_linear_vector", "linear_shade", "define_linear_shade", "define_circular_linear_shade", "define_sampled_linear_shade", "set_circular_vector", "circular_shade", "define_circular_shade", "define_circular_linear_shade", "define_sampled_circular_shade", "space", "CRLF", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedpath", "constructedpairs", "punkedfunction", "curvedfunction", "tightfunction", "punkedpath", "curvedpath", "tightpath", "punkedpairs", "curvedpairs", "tightpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "normalfill", "normaldraw", "visualizepaths", "naturalizepaths", "drawboundary", "drawwholepath", "visualizeddraw", "visualizedfill", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions", "undashed", "decorated", "redecorated", "undecorated", "passvariable", "passarrayvariable", "tostring", "format", "formatted", "startpassingvariable", "stoppassingvariable" }, + ["commands"]={ "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", "invsin", "invcos", "acosh", "asinh", "sinh", "cosh", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", "llcircle", "lrcircle", "urcircle", "ulcircle", "tcircle", "bcircle", "lcircle", "rcircle", "lltriangle", "lrtriangle", "urtriangle", "ultriangle", "smoothed", "cornered", "superellipsed", "randomized", "squeezed", "enlonged", "shortened", "punked", "curved", "unspiked", "simplified", "blownup", "stretched", "enlarged", "leftenlarged", "topenlarged", "rightenlarged", "bottomenlarged", "crossed", "laddered", "randomshifted", "interpolated", "paralleled", "cutends", "peepholed", "llenlarged", "lrenlarged", "urenlarged", "ulenlarged", "llmoved", "lrmoved", "urmoved", "ulmoved", "rightarrow", "leftarrow", "centerarrow", "boundingbox", "innerboundingbox", "outerboundingbox", "pushboundingbox", "popboundingbox", "bottomboundary", "leftboundary", "topboundary", "rightboundary", "xsized", "ysized", "xysized", "sized", "xyscaled", "intersection_point", "intersection_found", "penpoint", "bbwidth", "bbheight", "withshade", "withlinearshading", "withcircularshading", "withfromshadecolor", "withtoshadecolor", "withshading", "shadedinto", "withcircularshade", "withlinearshade", "cmyk", "spotcolor", "multitonecolor", "namedcolor", "drawfill", "undrawfill", "inverted", "uncolored", "softened", "grayed", "greyed", "onlayer", "along", "graphictext", "loadfigure", "externalfigure", "withmask", "figure", "register", "bitmapimage", "colordecimals", "ddecimal", "dddecimal", "ddddecimal", "textext", "thetextext", "rawtextext", "textextoffset", "verbatim", "thelabel", "label", "autoalign", "transparent", "withtransparency", "property", "properties", "withproperties", "asgroup", "infont", "set_linear_vector", "linear_shade", "define_linear_shade", "define_circular_linear_shade", "define_sampled_linear_shade", "set_circular_vector", "circular_shade", "define_circular_shade", "define_circular_linear_shade", "define_sampled_circular_shade", "space", "CRLF", "grayscale", "greyscale", "withgray", "withgrey", "colorpart", "readfile", "clearxy", "unitvector", "center", "epsed", "anchored", "originpath", "infinite", "break", "xstretched", "ystretched", "snapped", "pathconnectors", "function", "constructedpath", "constructedpairs", "punkedfunction", "curvedfunction", "tightfunction", "punkedpath", "curvedpath", "tightpath", "punkedpairs", "curvedpairs", "tightpairs", "evenly", "oddly", "condition", "pushcurrentpicture", "popcurrentpicture", "arrowpath", "tensecircle", "roundedsquare", "colortype", "whitecolor", "blackcolor", "normalfill", "normaldraw", "visualizepaths", "naturalizepaths", "drawboundary", "drawwholepath", "visualizeddraw", "visualizedfill", "draworigin", "drawboundingbox", "drawpath", "drawpoint", "drawpoints", "drawcontrolpoints", "drawcontrollines", "drawpointlabels", "drawlineoptions", "drawpointoptions", "drawcontroloptions", "drawlabeloptions", "draworiginoptions", "drawboundoptions", "drawpathoptions", "resetdrawoptions", "undashed", "decorated", "redecorated", "undecorated", "passvariable", "passarrayvariable", "tostring", "format", "formatted", "startpassingvariable", "stoppassingvariable" }, ["internals"]={ "nocolormodel", "greycolormodel", "graycolormodel", "rgbcolormodel", "cmykcolormodel", "shadefactor", "textextoffset", "normaltransparent", "multiplytransparent", "screentransparent", "overlaytransparent", "softlighttransparent", "hardlighttransparent", "colordodgetransparent", "colorburntransparent", "darkentransparent", "lightentransparent", "differencetransparent", "exclusiontransparent", "huetransparent", "saturationtransparent", "colortransparent", "luminositytransparent", "metapostversion", "maxdimensions" }, }
\ No newline at end of file diff --git a/context/data/scite/lexers/scite-context-lexer-mps.lua b/context/data/scite/lexers/scite-context-lexer-mps.lua index f0d88eb3b..96c5e9c3c 100644 --- a/context/data/scite/lexers/scite-context-lexer-mps.lua +++ b/context/data/scite/lexers/scite-context-lexer-mps.lua @@ -98,7 +98,7 @@ local number = token('number', number) local grouping = token('grouping', S("()[]{}")) -- can be an option local special = token('special', S("#()[]{}<>=:\"")) -- or else := <> etc split local texlike = token('warning', P("\\") * cstokentex^1) -local extra = token('extra', P("+-+") + P("++") + S("`~%^&_-+*/\'|\\")) +local extra = token('extra', S("`~%^&_-+*/\'|\\")) local nested = P { leftbrace * (V(1) + (1-rightbrace))^0 * rightbrace } local texlike = token('embedded', P("\\") * (P("MP") + P("mp")) * mptoken^1) diff --git a/context/data/scite/scite-context-data-context.properties b/context/data/scite/scite-context-data-context.properties index fbd958f8a..140b0d96b 100644 --- a/context/data/scite/scite-context-data-context.properties +++ b/context/data/scite/scite-context-data-context.properties @@ -143,49 +143,48 @@ gobblethreearguments gobblefourarguments gobblefivearguments gobblesixarguments gobbleeightarguments gobbleninearguments gobbletenarguments gobbleoneoptional gobbletwooptionals \ gobblethreeoptionals gobblefouroptionals gobblefiveoptionals dorecurse doloop \ exitloop dostepwiserecurse recurselevel recursedepth dofastloopcs \ -dowith newconstant setnewconstant setconstant setconstantvalue \ -newconditional settrue setfalse settruevalue setfalsevalue \ -newmacro setnewmacro newfraction newsignal dosingleempty \ -dodoubleempty dotripleempty doquadrupleempty doquintupleempty dosixtupleempty \ -doseventupleempty dosingleargument dodoubleargument dotripleargument doquadrupleargument \ -doquintupleargument dosixtupleargument doseventupleargument dosinglegroupempty dodoublegroupempty \ -dotriplegroupempty doquadruplegroupempty doquintuplegroupempty permitspacesbetweengroups dontpermitspacesbetweengroups \ -nopdfcompression maximumpdfcompression normalpdfcompression modulonumber dividenumber \ -getfirstcharacter doiffirstcharelse startnointerference stopnointerference twodigits \ -threedigits leftorright strut setstrut strutbox \ -strutht strutdp strutwd struthtdp begstrut \ -endstrut lineheight ordordspacing ordopspacing ordbinspacing \ -ordrelspacing ordopenspacing ordclosespacing ordpunctspacing ordinnerspacing \ -opordspacing opopspacing opbinspacing oprelspacing opopenspacing \ -opclosespacing oppunctspacing opinnerspacing binordspacing binopspacing \ -binbinspacing binrelspacing binopenspacing binclosespacing binpunctspacing \ -bininnerspacing relordspacing relopspacing relbinspacing relrelspacing \ -relopenspacing relclosespacing relpunctspacing relinnerspacing openordspacing \ -openopspacing openbinspacing openrelspacing openopenspacing openclosespacing \ -openpunctspacing openinnerspacing closeordspacing closeopspacing closebinspacing \ -closerelspacing closeopenspacing closeclosespacing closepunctspacing closeinnerspacing \ -punctordspacing punctopspacing punctbinspacing punctrelspacing punctopenspacing \ -punctclosespacing punctpunctspacing punctinnerspacing innerordspacing inneropspacing \ -innerbinspacing innerrelspacing inneropenspacing innerclosespacing innerpunctspacing \ -innerinnerspacing normalreqno startimath stopimath normalstartimath \ -normalstopimath startdmath stopdmath normalstartdmath normalstopdmath \ -uncramped cramped triggermathstyle mathstylefont mathsmallstylefont \ -mathstyleface mathsmallstyleface mathstylecommand mathpalette mathstylehbox \ -mathstylevbox mathstylevcenter mathstylevcenteredhbox mathstylevcenteredvbox mathtext \ -setmathsmalltextbox setmathtextbox triggerdisplaystyle triggertextstyle triggerscriptstyle \ -triggerscriptscriptstyle triggeruncrampedstyle triggercrampedstyle triggersmallstyle triggeruncrampedsmallstyle \ -triggercrampedsmallstyle triggerbigstyle triggeruncrampedbigstyle triggercrampedbigstyle luaexpr \ -expdoifelse expdoif expdoifnot expdoifcommonelse expdoifinsetelse \ -ctxdirectlua ctxlatelua ctxsprint ctxwrite ctxcommand \ -ctxdirectcommand ctxlatecommand ctxreport ctxlua luacode \ -lateluacode directluacode registerctxluafile ctxloadluafile luaversion \ -luamajorversion luaminorversion ctxluacode luaconditional luaexpanded \ -startluaparameterset stopluaparameterset luaparameterset definenamedlua obeylualines \ -obeyluatokens startluacode stopluacode startlua stoplua \ -carryoverpar assumelongusagecs Umathbotaccent righttolefthbox lefttorighthbox \ -righttoleftvbox lefttorightvbox righttoleftvtop lefttorightvtop rtlhbox \ -ltrhbox rtlvbox ltrvbox rtlvtop ltrvtop \ -autodirhbox autodirvbox autodirvtop lefttoright righttoleft \ -synchronizelayoutdirection synchronizedisplaydirection synchronizeinlinedirection lesshyphens morehyphens \ -nohyphens dohyphens Ucheckedstartdisplaymath Ucheckedstopdisplaymath +dowith newconstant setnewconstant newconditional settrue \ +setfalse setconstant newmacro setnewmacro newfraction \ +newsignal dosingleempty dodoubleempty dotripleempty doquadrupleempty \ +doquintupleempty dosixtupleempty doseventupleempty dosingleargument dodoubleargument \ +dotripleargument doquadrupleargument doquintupleargument dosixtupleargument doseventupleargument \ +dosinglegroupempty dodoublegroupempty dotriplegroupempty doquadruplegroupempty doquintuplegroupempty \ +permitspacesbetweengroups dontpermitspacesbetweengroups nopdfcompression maximumpdfcompression normalpdfcompression \ +modulonumber dividenumber getfirstcharacter doiffirstcharelse startnointerference \ +stopnointerference twodigits threedigits leftorright strut \ +setstrut strutbox strutht strutdp strutwd \ +struthtdp begstrut endstrut lineheight ordordspacing \ +ordopspacing ordbinspacing ordrelspacing ordopenspacing ordclosespacing \ +ordpunctspacing ordinnerspacing opordspacing opopspacing opbinspacing \ +oprelspacing opopenspacing opclosespacing oppunctspacing opinnerspacing \ +binordspacing binopspacing binbinspacing binrelspacing binopenspacing \ +binclosespacing binpunctspacing bininnerspacing relordspacing relopspacing \ +relbinspacing relrelspacing relopenspacing relclosespacing relpunctspacing \ +relinnerspacing openordspacing openopspacing openbinspacing openrelspacing \ +openopenspacing openclosespacing openpunctspacing openinnerspacing closeordspacing \ +closeopspacing closebinspacing closerelspacing closeopenspacing closeclosespacing \ +closepunctspacing closeinnerspacing punctordspacing punctopspacing punctbinspacing \ +punctrelspacing punctopenspacing punctclosespacing punctpunctspacing punctinnerspacing \ +innerordspacing inneropspacing innerbinspacing innerrelspacing inneropenspacing \ +innerclosespacing innerpunctspacing innerinnerspacing normalreqno startimath \ +stopimath normalstartimath normalstopimath startdmath stopdmath \ +normalstartdmath normalstopdmath uncramped cramped triggermathstyle \ +mathstylefont mathsmallstylefont mathstyleface mathsmallstyleface mathstylecommand \ +mathpalette mathstylehbox mathstylevbox mathstylevcenter mathstylevcenteredhbox \ +mathstylevcenteredvbox mathtext setmathsmalltextbox setmathtextbox triggerdisplaystyle \ +triggertextstyle triggerscriptstyle triggerscriptscriptstyle triggeruncrampedstyle triggercrampedstyle \ +triggersmallstyle triggeruncrampedsmallstyle triggercrampedsmallstyle triggerbigstyle triggeruncrampedbigstyle \ +triggercrampedbigstyle luaexpr expdoifelse expdoif expdoifnot \ +expdoifcommonelse expdoifinsetelse ctxdirectlua ctxlatelua ctxsprint \ +ctxwrite ctxcommand ctxdirectcommand ctxlatecommand ctxreport \ +ctxlua luacode lateluacode directluacode registerctxluafile \ +ctxloadluafile luaversion luamajorversion luaminorversion ctxluacode \ +luaconditional luaexpanded startluaparameterset stopluaparameterset luaparameterset \ +definenamedlua obeylualines obeyluatokens startluacode stopluacode \ +startlua stoplua carryoverpar assumelongusagecs Umathbotaccent \ +righttolefthbox lefttorighthbox righttoleftvbox lefttorightvbox righttoleftvtop \ +lefttorightvtop rtlhbox ltrhbox rtlvbox ltrvbox \ +rtlvtop ltrvtop autodirhbox autodirvbox autodirvtop \ +lefttoright righttoleft synchronizelayoutdirection synchronizedisplaydirection synchronizeinlinedirection \ +lesshyphens morehyphens nohyphens dohyphens diff --git a/context/data/scite/scite-context-data-metafun.properties b/context/data/scite/scite-context-data-metafun.properties index 9381b4f8d..c0b080982 100644 --- a/context/data/scite/scite-context-data-metafun.properties +++ b/context/data/scite/scite-context-data-metafun.properties @@ -3,49 +3,49 @@ sqr log ln exp \ inv pow pi radian tand \ cotd sin cos tan cot \ atan asin acos invsin invcos \ -invtan acosh asinh sinh cosh \ -paired tripled unitcircle fulldiamond unitdiamond \ -fullsquare llcircle lrcircle urcircle ulcircle \ -tcircle bcircle lcircle rcircle lltriangle \ -lrtriangle urtriangle ultriangle smoothed cornered \ -superellipsed randomized squeezed enlonged shortened \ -punked curved unspiked simplified blownup \ -stretched enlarged leftenlarged topenlarged rightenlarged \ -bottomenlarged crossed laddered randomshifted interpolated \ -paralleled cutends peepholed llenlarged lrenlarged \ -urenlarged ulenlarged llmoved lrmoved urmoved \ -ulmoved rightarrow leftarrow centerarrow boundingbox \ -innerboundingbox outerboundingbox pushboundingbox popboundingbox bottomboundary \ -leftboundary topboundary rightboundary xsized ysized \ -xysized sized xyscaled intersection_point intersection_found \ -penpoint bbwidth bbheight withshade withlinearshading \ -withcircularshading withfromshadecolor withtoshadecolor withshading shadedinto \ -withcircularshade withlinearshade cmyk spotcolor multitonecolor \ -namedcolor drawfill undrawfill inverted uncolored \ -softened grayed greyed onlayer along \ -graphictext loadfigure externalfigure withmask figure \ -register bitmapimage colordecimals ddecimal dddecimal \ -ddddecimal textext thetextext rawtextext textextoffset \ -verbatim thelabel label autoalign transparent \ -withtransparency property properties withproperties asgroup \ -infont set_linear_vector linear_shade define_linear_shade define_circular_linear_shade \ -define_sampled_linear_shade set_circular_vector circular_shade define_circular_shade define_circular_linear_shade \ -define_sampled_circular_shade space CRLF grayscale greyscale \ -withgray withgrey colorpart readfile clearxy \ -unitvector center epsed anchored originpath \ -infinite break xstretched ystretched snapped \ -pathconnectors function constructedpath constructedpairs punkedfunction \ -curvedfunction tightfunction punkedpath curvedpath tightpath \ -punkedpairs curvedpairs tightpairs evenly oddly \ -condition pushcurrentpicture popcurrentpicture arrowpath tensecircle \ -roundedsquare colortype whitecolor blackcolor normalfill \ -normaldraw visualizepaths naturalizepaths drawboundary drawwholepath \ -visualizeddraw visualizedfill draworigin drawboundingbox drawpath \ -drawpoint drawpoints drawcontrolpoints drawcontrollines drawpointlabels \ -drawlineoptions drawpointoptions drawcontroloptions drawlabeloptions draworiginoptions \ -drawboundoptions drawpathoptions resetdrawoptions undashed decorated \ -redecorated undecorated passvariable passarrayvariable tostring \ -format formatted startpassingvariable stoppassingvariable +acosh asinh sinh cosh paired \ +tripled unitcircle fulldiamond unitdiamond fullsquare \ +llcircle lrcircle urcircle ulcircle tcircle \ +bcircle lcircle rcircle lltriangle lrtriangle \ +urtriangle ultriangle smoothed cornered superellipsed \ +randomized squeezed enlonged shortened punked \ +curved unspiked simplified blownup stretched \ +enlarged leftenlarged topenlarged rightenlarged bottomenlarged \ +crossed laddered randomshifted interpolated paralleled \ +cutends peepholed llenlarged lrenlarged urenlarged \ +ulenlarged llmoved lrmoved urmoved ulmoved \ +rightarrow leftarrow centerarrow boundingbox innerboundingbox \ +outerboundingbox pushboundingbox popboundingbox bottomboundary leftboundary \ +topboundary rightboundary xsized ysized xysized \ +sized xyscaled intersection_point intersection_found penpoint \ +bbwidth bbheight withshade withlinearshading withcircularshading \ +withfromshadecolor withtoshadecolor withshading shadedinto withcircularshade \ +withlinearshade cmyk spotcolor multitonecolor namedcolor \ +drawfill undrawfill inverted uncolored softened \ +grayed greyed onlayer along graphictext \ +loadfigure externalfigure withmask figure register \ +bitmapimage colordecimals ddecimal dddecimal ddddecimal \ +textext thetextext rawtextext textextoffset verbatim \ +thelabel label autoalign transparent withtransparency \ +property properties withproperties asgroup infont \ +set_linear_vector linear_shade define_linear_shade define_circular_linear_shade define_sampled_linear_shade \ +set_circular_vector circular_shade define_circular_shade define_circular_linear_shade define_sampled_circular_shade \ +space CRLF grayscale greyscale withgray \ +withgrey colorpart readfile clearxy unitvector \ +center epsed anchored originpath infinite \ +break xstretched ystretched snapped pathconnectors \ +function constructedpath constructedpairs punkedfunction curvedfunction \ +tightfunction punkedpath curvedpath tightpath punkedpairs \ +curvedpairs tightpairs evenly oddly condition \ +pushcurrentpicture popcurrentpicture arrowpath tensecircle roundedsquare \ +colortype whitecolor blackcolor normalfill normaldraw \ +visualizepaths naturalizepaths drawboundary drawwholepath visualizeddraw \ +visualizedfill draworigin drawboundingbox drawpath drawpoint \ +drawpoints drawcontrolpoints drawcontrollines drawpointlabels drawlineoptions \ +drawpointoptions drawcontroloptions drawlabeloptions draworiginoptions drawboundoptions \ +drawpathoptions resetdrawoptions undashed decorated redecorated \ +undecorated passvariable passarrayvariable tostring format \ +formatted startpassingvariable stoppassingvariable keywordclass.metafun.internals=\ nocolormodel greycolormodel graycolormodel rgbcolormodel \ diff --git a/context/data/scite/scite-context-readme.pdf b/context/data/scite/scite-context-readme.pdf Binary files differindex 99f05a2a5..b6a751a36 100644 --- a/context/data/scite/scite-context-readme.pdf +++ b/context/data/scite/scite-context-readme.pdf diff --git a/context/data/scite/scite-context-readme.tex b/context/data/scite/scite-context-readme.tex index 42f5e0a98..ef1475fa2 100644 --- a/context/data/scite/scite-context-readme.tex +++ b/context/data/scite/scite-context-readme.tex @@ -821,18 +821,12 @@ from the on|-|line help pages. \NC \type{Ctrl+Right} \NC next word; \type{Shift} extends selection \NC \NR \NC \type{Ctrl+/} \NC previous word part; \type{Shift} extends selection \NC \NR \NC \type{Ctrl+\ } \NC next word part; \type{Shift} extends selection \NC \NR -\ML -\NC \type{F12 / Ctrl+F7} \NC check (or process) \NC \NR -\NC \type{Ctrl+F12 / Ctrl+F7} \NC process (run) \NC \NR -\NC \type{Alt+F12 / Ctrl+F7} \NC process (run) using the luajit vm (if applicable) \NC \NR \LL \stoptabulate \stopbuffer \getbuffer[keybindings] -\page - \subject{Affiliation} \starttabulate[|l|l|] diff --git a/context/data/scite/scite-context.properties b/context/data/scite/scite-context.properties index bc1af717c..caf230de7 100644 --- a/context/data/scite/scite-context.properties +++ b/context/data/scite/scite-context.properties @@ -115,11 +115,9 @@ name.metafun.console=$(name.context.console) name.example.console=$(name.context.console) name.context.mtxrun=mtxrun --autogenerate -name.context.mtxrunjit=mtxrunjit --autogenerate name.context.check=$(name.context.mtxrun) --script check name.context.run=$(name.context.mtxrun) --script context $(name.flag.pdfopen) -name.context.runjit=$(name.context.mtxrunjit) --script context $(name.flag.pdfopen) name.context.texshow=$(name.context.mtxrun) texshow name.context.purge=$(name.context.mtxrun) --context --purge --all name.context.showcase=$(name.context.mtxrun) --launch showcase.pdf @@ -164,20 +162,20 @@ import scite-ctx # hard coded compile / build / go -command.build.$(file.patterns.context)=$(name.context.check) $(FileNameExt) -command.build.$(file.patterns.metafun)= -command.build.$(file.patterns.example)=$(name.example.xmlcheck) $(FileNameExt) -command.build.*.fo=$(name.example.xmlcheck) $(FileNameExt) +command.compile.$(file.patterns.context)=$(name.context.check) $(FileNameExt) +command.compile.$(file.patterns.metafun)= +command.compile.$(file.patterns.example)=$(name.example.xmlcheck) $(FileNameExt) +command.compile.*.fo=$(name.example.xmlcheck) $(FileNameExt) -command.compile.$(file.patterns.context)=$(name.context.run) $(FileNameExt) -command.compile.$(file.patterns.metafun)=$(name.context.run) $(name.flag.pdfopen) $(FileNameExt) -command.compile.$(file.patterns.example)=$(name.context.run) --forcexml $(FileNameExt) -command.compile.*.fo=$(name.context.run) $(name.flag.pdfopen) --forcexml --use=foxet $(FileNameExt) +command.build.$(file.patterns.context)=$(name.context.run) $(FileNameExt) +command.build.$(file.patterns.metafun)=$(name.context.mtxrun) --script context $(name.flag.pdfopen) $(FileNameExt) +command.build.$(file.patterns.example)=$(name.context.run) --forcexml $(FileNameExt) +command.build.*.fo=$(name.context.run) $(name.flag.pdfopen) --forcexml --use=foxet $(FileNameExt) -command.compile.subsystem.$(file.patterns.context)=1 -command.compile.subsystem.$(file.patterns.metafun)=1 -command.compile.subsystem.$(file.patterns.example)=1 -command.compile.subsystem.*.fo=1 +command.build.subsystem.$(file.patterns.context)=1 +command.build.subsystem.$(file.patterns.metafun)=1 +command.build.subsystem.$(file.patterns.example)=1 +command.build.subsystem.*.fo=1 if PLAT_WIN command.go.$(file.patterns.context)=$(FileName).pdf @@ -220,24 +218,6 @@ command.1.subsystem.$(file.patterns.context)=1 command.1.subsystem.$(file.patterns.metafun)=1 command.1.subsystem.$(file.patterns.example)=1 -command.name.29.*=Run with jit -command.subsystem.29.*=1 -command.29.$(file.patterns.context)=$(name.context.runjit) $(FileNameExt) -command.29.$(file.patterns.metafun)=$(name.context.runjit) $(FileNameExt) --metapost -command.29.$(file.patterns.exmaple)=$(name.context.runjit) $(FileNameExt) --xml -command.groupundo.29.*=yes -command.save.before.29.*=2 -command.shortcut.29.*=Alt+F12 - -command.name.30.*=Run with jit -command.subsystem.30.*=1 -command.30.$(file.patterns.context)=$(name.context.runjit) $(FileNameExt) -command.30.$(file.patterns.metafun)=$(name.context.runjit) $(FileNameExt) --metapost -command.30.$(file.patterns.exmaple)=$(name.context.runjit) $(FileNameExt) --xml -command.groupundo.30.*=yes -command.save.before.30.*=2 -command.shortcut.30.*=Alt+F7 - # 2 : pdf viewing command.name.2.$(file.patterns.context)=View PDF File with GhostScript @@ -357,9 +337,10 @@ highlight.indentation.guides=1 # Editor: keys user.shortcuts=\ -F12|IDM_BUILD|\ -Ctrl+F12|IDM_COMPILE|\ +F12|IDM_COMPILE|\ +Ctrl+F12|IDM_BUILD|\ Shift+F12|IDM_GO|\ +Alt+F12|IDM_STOPEXECUTE|\ os.x.home.end.keys=0 diff --git a/context/data/scite/scite-ctx.properties b/context/data/scite/scite-ctx.properties index acbb33c0b..d56ae653d 100644 --- a/context/data/scite/scite-ctx.properties +++ b/context/data/scite/scite-ctx.properties @@ -69,19 +69,14 @@ ctx.spellcheck.wordsize.uk=4 ctx.spellcheck.wordsize.nl=4 ctx.helpinfo=\ - Shift + F11 pop up menu with ctx options|\ + Shift + F11 pop up menu with ctx options|\ |\ - Ctrl + B check spelling|\ - Ctrl + M wrap text (auto indent)|\ - Ctrl + R reset spelling results|\ - Ctrl + I insert template|\ - Ctrl + E open log file|\ - Ctrl + + toggle strip|\ - |\ - F7 / F12 check (or process)|\ - Ctrl + F7 / F12 process|\ - Alt + F7 / F12 process with jit|\ - shift + F7 / F12 launch + Ctrl + B check spelling|\ + Ctrl + M wrap text (auto indent)|\ + Ctrl + R reset spelling results|\ + Ctrl + I insert template|\ + Ctrl + E open log file|\ + Ctrl + + toggle strip command.name.21.$(file.patterns.context)=CTX Action List command.subsystem.21.$(file.patterns.context)=3 diff --git a/doc/context/manuals/allkind/mkiv-publications.bib b/doc/context/manuals/allkind/mkiv-publications.bib deleted file mode 100644 index e94f43202..000000000 --- a/doc/context/manuals/allkind/mkiv-publications.bib +++ /dev/null @@ -1,34 +0,0 @@ -@book{demo-001, - author = "Hans Hagen", - title = "\BIBTEX, the \CONTEXT\ way", - year = "2013", -} - -@book{demo-002, - crossref = "demo-001" - year = "2014", -} - -@book{demo-003, - author = "Hans Hagen and Ton Otten", - title = "Typesetting education documents", - year = "1996", - comment = "a non-existing document", -} - -@book{demo-004, - author = "Luigi Scarso", - title = "Designing high speed trains", - year = "2021", - comment = "still to be published", -} - -@book{demo-005, - author = "author", - title = "title", - year = "year", - serial = "serial", - doi = "doi", - url = "url", - pages = "pages" -} diff --git a/doc/context/manuals/allkind/mkiv-publications.tex b/doc/context/manuals/allkind/mkiv-publications.tex deleted file mode 100644 index 3300a0f53..000000000 --- a/doc/context/manuals/allkind/mkiv-publications.tex +++ /dev/null @@ -1,1325 +0,0 @@ -% language=uk - -% \setupbtxrendering[continue=yes] -% \btxfield{manipulator_a->manipulator_b->fieldname} - -% engine=luajittex - -% criterium: all + sorttype=cite => citex before rest -% criterium: all + sorttype=database => database order -% criterium: used -% -% numbering: label, short, indexinlist, indexused -% -% maybeyear -% -% \cite[data][whatever] - -% \showframe - -\usemodule[abr-02] -\usemodule[set-11] - -\loadsetups[publications-en.xml] \enablemode[interface:setup:defaults] - -\setupbackend - [export=yes, - xhtml=yes, - css=export-example.css] - -\setupexport - [hyphen=yes, - width=60em] - -% \input publ-tmp.mkiv - -\setupbodyfont - [dejavu,10pt] - -\setuphead - [chapter] - [header=high, - style=\bfc, - color=darkmagenta] - -\setuplayout - [topspace=2cm, - bottomspace=1cm, - header=0cm, - width=middle, - height=middle] - -\setupwhitespace - [big] - -\setuptyping - [color=darkmagenta] - -\setuptyping - [keeptogether=yes] - -\setuptype - [color=darkcyan] - -\setupfootertexts - [pagenumber] - -\setupMPgraphics - [mpy=\jobname.mpy] - -\setupinteraction - [state=start, - color=darkcyan, - contrastcolor=darkyellow] - -\starttext - -\startMPpage - - StartPage ; - - % input "mkiv-publications.mpy" ; - - picture pic ; pic := image ( - path pth ; pth := ((0,0) for i=1 step 2 until 20 : -- (i,1) -- (i+1,0) endfor) ; - for i=0 upto 9 : draw pth shifted (0,2*i) ; endfor ; - ) ; - - % picture btx ; btx := textext("\ssbf BIBTEX") ; - % picture ctx ; ctx := textext("\ssbf THE CONTEXT WAY") ; - picture btx ; btx := image(graphictext("\ssbf BIBTEX") withfillcolor white) ; - picture ctx ; ctx := image(graphictext("\ssbf THE CONTEXT WAY") withfillcolor white) ; - - pic := pic shifted - llcorner pic ; - btx := btx shifted - llcorner btx ; - ctx := ctx shifted - llcorner ctx ; - - pic := pic xysized (PaperWidth,PaperHeight) ; - btx := btx xsized (2PaperWidth/3) shifted (.25PaperWidth,.15PaperHeight) ; - ctx := ctx xsized (2PaperWidth/3) shifted (.25PaperWidth,.075PaperHeight) ; - - fill Page withcolor \MPcolor{darkcyan} ; - - draw pic withcolor \MPcolor{darkmagenta} ; - draw btx withcolor \MPcolor{lightgray} ; - draw ctx withcolor \MPcolor{lightgray} ; - - % draw boundingbox btx ; - % draw boundingbox ctx ; - - StopPage ; - -\stopMPpage - - -\startfrontmatter - -\starttitle[title=Contents] - \placelist[chapter,section][color=black] -\stoptitle - -\startchapter[title=Introduction] - -This manual describes how \MKIV\ handles bibliographies. Support in \CONTEXT\ -started in \MKII for \BIBTEX, using a module written by Taco Hoekwater. Later his -code was adapted to \MKIV, but because users demanded more, I decided that -reimplementing made more sense than patching. In particular, through the use of -\LUA, the \BIBTEX\ data files can be easily directly parsed, thus liberating -\CONTEXT\ from the dependency on an external \BIBTEX\ executable. The CritEd -project (by Thomas Schmitz, Alan Braslau, Luigi Scarso and myself) was a good -reason to undertake this rewrite. As part that project users were invited to come -up with ideas about extensions. Not all of them are (yet) honored, but the -rewrite makes more functionality possible. - -This manual is dedicated to Taco Hoekwater who in a previous century implemented -the first \BIBTEX\ module and saw it morf into a \TEX||\LUA\ hybrid in this -century. The fact that there was support for bibliographies made it possible for -users to use \CONTEXT\ in an academic environment, dominated by bibliographic -databases encoded in the \BIBTEX\ format. - -\startlines -Hans Hagen -PRAGMA ADE -Hasselt NL -\stoplines - -\stopchapter - -\stopfrontmatter - -\startbodymatter - -\startchapter[title=The database] - -The \BIBTEX\ format is rather popular in the \TEX\ community and even with its -shortcomings it will stay around for a while. Many publication websites can -export and many tools are available to work with this database format. It is -rather simple and looks a bit like \LUA\ tables. Unfortunately the content can be -polluted with non|-|standardized \TEX\ commands which complicates pre- or -postprocessing outside \TEX. In that sense a \BIBTEX\ database is often not coded -neutrally. Some limitations, like the use of commands to encode accented -characters root in the \ASCII\ world and can be bypassed by using \UTF\ instead -(as handled somewhat in \LATEX\ through extensions such as \type {bibtex8}). - -The normal way to deal with a bibliography is to refer to entries using a unique -tag or key. When a list of entries is typeset, this reference can be used for -linking purposes. The typeset list can be processed and sorted using the \type -{bibtex} program that converts the database into something more \TEX\ friendly (a -\type {.bbl} file). I never used the program myself (nor bibliographies) so I -will not go into too much detail here, if only because all I say can be wrong. - -In \CONTEXT\ we no longer use the \type {bibtex} program: we just use -database files and deal with the necessary manipulations directly in \CONTEXT. -One or more such databases can be used and combined with additional entries -defined within the document. We can have several such datasets active at the same -time. - -A \BIBTEX\ file looks like this: - -\starttyping -@Article{sometag, - author = "An Author and Another One", - title = "A hopefully meaningful title", - journal = maps, - volume = "25", - number = "2", - pages = "5--9", - month = mar, - year = "2013", - ISSN = "1234-5678", -} -\stoptyping - -Normally a value is given between quotes (or curly brackets) but single words are -also OK (there is no real benefit in not using quotes, so we advise to always use -them). There can be many more fields and instead of strings one can use -predefined shortcuts. The title for example quite often contains \TEX\ macros. -Some fields, like \type {pages} have funny characters such as the endash -(typically as \type {--}) so we have a mixture of data and typesetting -directives. If you are covering non||english references, you often need -characters that are not in the \ASCII\ subset but \CONTEXT\ is quite happy with -\UTF. If your database file uses old|-|fashioned \TEX\ accent commands then these -will be internally converted automatically to \UTF. Commands (macros) are -converted to an indirect call, which is quite robust. - -The \BIBTEX\ files are loaded in memory as \LUA\ table but can be converted to -\XML\ so that we can access them in a more flexible way, but that is a subject -for specialists. - -In the old \MKII\ setup we have two kinds of entries: the ones that come from the -\BIBTEX\ run and user supplied ones. We no longer rely on \BIBTEX\ output but we -do still support the user supplied definitions. These were in fact prepared in a -way that suits the processing of \BIBTEX\ generated entries. The next variant -reflects the \CONTEXT\ recoding of the old \BIBTEX\ output. - -\starttyping -\startpublication[k=Hagen:Second,t=article,a={Hans Hagen},y=2013,s=HH01] - \artauthor[]{Hans}[H.]{}{Hagen} - \arttitle{Who knows more?} - \journal{MyJournal} - \pubyear{2013} - \month{8} - \volume{1} - \issue{3} - \issn{1234-5678} - \pages{123--126} -\stoppublication -\stoptyping - -The split \type {\artauthor} fields are collapsed into a single \type {author} -field as we deal with the splitting later when it gets parsed in \LUA. The \type -{\artauthor} syntax is only kept around for backward compatibility with the -previous use of \BIBTEX. - -In the new setup we support these variants as well: - -\starttyping -\startpublication[k=Hagen:Third,t=article] - \author{Hans Hagen} - \title{Who knows who?} - ... -\stoppublication -\stoptyping - -and - -\starttyping -\startpublication[tag=Hagen:Third,category=article] - \author{Hans Hagen} - \title{Who knows who?} - ... -\stoppublication -\stoptyping - -and - -\starttyping -\startpublication - \tag{Hagen:Third} - \category{article} - \author{Hans Hagen} - \title{Who knows who?} - ... -\stoppublication -\stoptyping - -Because internally the entries are \LUA\ tables, we also support loading of \LUA\ -based definitions: - -\starttyping -return { - ["Hagen:First"] = { - author = "Hans Hagen", - category = "article", - issn = "1234-5678", - issue = "3", - journal = "MyJournal", - month = "8", - pages = "123--126", - tag = "Hagen:First", - title = "Who knows nothing?", - volume = "1", - year = "2013", - }, -} -\stoptyping - -Files set up like this can be loaded too. The following \XML\ input is rather -close to this, and is also accepted as input. - -\starttyping -<?xml version="2.0" standalone="yes" ?> -<bibtex> - <entry tag="Hagen:First" category="article"> - <field name="author">Hans Hagen</field> - <field name="category">article</field> - <field name="issn">1234-5678</field> - <field name="issue">3</field> - <field name="journal">MyJournal</field> - <field name="month">8</field> - <field name="pages">123--126</field> - <field name="tag">Hagen:First</field> - <field name="title">Who knows nothing?</field> - <field name="volume">1</field> - <field name="year">2013</field> - </entry> -</bibtex> -\stoptyping - -{\em Todo: Add some remarks about loading EndNote and RIS formats, but first we -need to complete the tag mapping (on Alan's plate).} - -So the user has a rather wide choice of formatting style for bibliography -database files. - -\stopchapter - -You can load more data than you actually need. Only entries that are referred to -explicitly through the \type {\cite} and \type {\nocite} commands will be shown -in lists. We will cover these details later. - -\startchapter[title=Commands in entries] - -One unfortunate aspect commonly found in \BIBTEX\ files is that they often -contain \TEX\ commands. Even worse is that there is no standard on what these -commands can be and what they mean, at least not formally, as \BIBTEX\ is a -program intended to be used with many variants of \TEX\ style: plain, \LATEX, and -others. This means that we need to define our use of these typesetting commands. -However, in most cases, they are just abbreviations or font switches and these -are often known. Therefore, \CONTEXT\ will try to resolve them before reporting -an issue. In the log file there is a list of commands that has been seen in the -loaded databases. For instance, loading \type {tugboat.bib} gives a long list of -commands of which we show a small set here: - -\starttyping -publications > start used btx commands - -publications > standard CONTEXT 1 known -publications > standard ConTeXt 4 known -publications > standard TeXLive 3 KNOWN -publications > standard eTeX 1 known -publications > standard hbox 6 known -publications > standard sltt 1 unknown - -publications > stop used btxcommands -\stoptyping - -You can define unknown commands, or overload existing definitions in the -following way: - -\starttyping -\definebtxcommand\TUB {TUGboat} -\definebtxcommand\sltt{\tt} -\definebtxcommand\<#1>{\type{#1}} -\stoptyping - -Unknown commands do not stall processing, but their names are then typeset in a -mono|-|spaced font so they probably stand out for proofreading. You can -access the commands with \type {\btxcommand {...}}, as in: - -\startbuffer -commands like \btxcommand{MySpecialCommand} are handled in an indirect way -\stopbuffer - -\typebuffer - -As this is an undefined command we get: \quotation {\inlinebuffer}. - -?? - -\stopchapter - -\startchapter[title=Datasets] - -Normally in a document you will use only one bibliographic database, whether or -not distributed over multiple files. Nevertheless we support multiple databases as well -which is why we talk of datasets instead. A dataset is loaded with the \type -{\usebtxdataset} command. Although currently it is not necessary to define a -(default) dataset you can best do this because in the future we might provide more -options. Here are some examples: - -\starttyping -\definebtxdataset[standard] - -\usebtxdataset[standard][tugboat.bib] -\usebtxdataset[standard][mtx-bibtex-output.xml] -\usebtxdataset[standard][test-001-btx-standard.lua] -\stoptyping - -These three suffixes are understood by the loader. Here the dataset has the name -\type {standard} and the three database files are merged, where later entries having the -same tag overload previous ones. Definitions in the document source (coded in \TEX\ -speak) are also added, and they are saved for successive runs. This means that if -you load and define entries, they will be known at a next run beforehand, so that -references to them are independent of when loading and definitions take place. - -\showsetup{setupbtxdataset} - -\showsetup{definebtxdataset} - -\showsetup{usebtxdataset} - -In this document we use some example databases, so let's load one of them now: - -\startbuffer -\definebtxdataset[example] - -\usebtxdataset[example][mkiv-publications.bib] -\stopbuffer - -\typebuffer \getbuffer - -You can ask for an overview of entries in a dataset with: - -\startbuffer -\showbtxdatasetfields[example] -\stopbuffer - -\typebuffer - -this gives: - -\getbuffer - -You can set the current active dataset with - -\starttyping -\setbtxdataset[standard] -\stoptyping - -but most publication|-|related commands accept optional arguments that denote the -dataset and references to entries can be prefixed with a dataset identifier.. More -about that later. - -Sometimes you want to check a database. One way of doing that is the following: - -\startbuffer -\definebtxdataset[check] - -\usebtxdataset[check][mkiv-publications-check.bib] - -\showbtxdatasetcompleteness[check] -\stopbuffer - -\typebuffer - -The database like like this: - -\typefile{mkiv-publications-check.bib} - -The completeness check shows (with green field names) the required fields and -when one is missing this is indicated in red. In blue we show what gets -inherited. - -\getbuffer - -\stopchapter - -\startchapter[title=Renderings] - -A list of publications can be rendered at any place in the document. A database -can be much larger than needed for a document. The same is true for the fields -that make up an entry. Here is the list of fields that are currently handled, but -of course there can be additional ones: - - -\startalignment[flushleft,verytolerant,nothyphenated] -\startluacode -local fields = publications.tracers.fields - -for i=1,#fields do - if i > 1 then - context(", ") - end - context.type(fields[i]) -end -\stopluacode -\stopalignment - -If you want to see what publications are in the database, the easiest way is to -ask for a complete list: - -\startbuffer -\definebtxrendering - [example] - [dataset=example, - method=local, - alternative=apa] -\placelistofpublications % \placebtxrendering - [example] - [criterium=all] -\stopbuffer - -\typebuffer - -This gives: - -\getbuffer - -The rendering itself is somewhat complex to set up because we have not only many -different standards but also many fields that can be set up. This means that -there are several commands involved. Often there is a prescribed style to render -bibliographic descriptions, for example \type {apa}. A rendering is setup and -defined with: - -\showsetup[setupbtxrendering] -%showrootvalues[btxrendering] -\showsetup[definebtxrendering] - -And a list of such descriptions is generated with: - -\showsetup[placebtxrendering] - -A dataset can have all kind of entries: - -\startalignment[flushleft,verytolerant,nothyphenated] -\startluacode - local categories = publications.tracers.categories - - for i=1,#categories do - if i > 1 then - context(", ") - end - context.type(categories[i]) - end -\stopluacode -\stopalignment - -Each has its own rendering variant. To keep things simple we have their settings -separated. However, these settings are shared for all rendering alternatives. In -practice this is seldom a problem in a publication as only one rendering -alternative will be active. If this be not sufficient, you can always group local -settings in a setup and hook that into the specific rendering. - -\showsetup[setupbtxlistvariant] -%showrootvalues[btxlistvariant] -\showsetup[definebtxlistvariant] - -Examples of list variants are: - -\startluacode - local variants = publications.tracers.listvariants - - for i=1,#variants do - context.showinstancevalues( { "btxlistvariant" }, { variants[i] }) - end -\stopluacode - -The exact rendering of list entries is determined by the \type {alternative} key -and defaults to \type {apa} which uses definitions from \type -{publ-imp-apa.mkiv}. If you look at that file you will see that each category has -its own setup. You may also notice that additional tests are needed to make sure -that empty fields don't trigger separators and such. - -% \showsetup{setuplists} - -There are a couple of accessors and helpers to get the job done. When you want to -fetch a field from the current entry you use \type {\btxfield}. In most cases -you want to make sure this field has a value, for instance because you don't want -fences or punctuation that belongs to a field. - -\starttyping -\btxdoif {title} { - \bold{\btxfield{title}}, -} -\stoptyping - -There are three test macros: - -\starttyping -\btxdoifelse{fieldname}{action when found}{action when not found} -\btxdoif {fieldname}{action when found} -\btxdoifnot {fieldname} {action when not found} -\stoptyping - -An extra conditional is available for testing interactivity: - -\starttyping -\btxdoifelseinteraction{action when true}{action when false} -\stoptyping - -In addition there is also a conditional \type {\btxinteractive} which is -more efficient, although in practice efficiency is not so important here. - -There are three commands to flush data: - -\starttabulate[|||] % Funny usage here! Could not tabulate work without - % even specifying the number of columns? -\NC \type {\btxfield} \NC fetch a explicit field (e.g. \type {year}) \NC \NR -\NC \type {\btxdetail} \NC fetch a derived field (e.g. \type {short}) \NC \NR -\NC \type {\btxflush} \NC fetch a derived or explicit field \NC \NR -\stoptabulate - -Normally you can use \type {\btxfield} or \type {\btxflush} as derived fields -just like analyzed author fields are flushed in a special way. - -You can improve readability by using setups, for instance: - -\starttyping -\btxdoifelse {author} { - \btxsetup{btx:apa:author:yes} -} { - \btxsetup{btx:apa:author:nop} -} -\stoptyping - -Keep in mind that normally you don't need to mess with definitions like this -because standard rendering styles are provided. These styles use a few helpers -that inject symbols but also take care of leading and trailing spaces: - -\starttabulate[|||] -\NC \type {\btxspace } \NC before \btxspace after \NC \NR -\NC \type {\btxperiod } \NC before \btxperiod after \NC \NR -\NC \type {\btxcomma } \NC before \btxcomma after \NC \NR -\NC \type {\btxlparent } \NC before \btxlparent after \NC \NR -\NC \type {\btxrparent } \NC before \btxrparent after \NC \NR -\NC \type {\btxlbracket} \NC before \btxlbracket after \NC \NR -\NC \type {\btxrbracket} \NC before \btxrbracket after \NC \NR -\stoptabulate - -So, the previous example setup can be rewritten as: - -\starttyping -\btxdoif {title} { - \bold{\btxfield{title}} - \btxcomma -} -\stoptyping - -There is a special command for rendering a (combination) of authors: - -\starttyping -\btxflushauthor{author} -\btxflushauthor{editor} -\btxflushauthor[inverted]{editor} -\stoptyping - -Instead of the last one you can also use: - -\starttyping -\btxflushauthorinverted{editor} -\stoptyping - -You can use a (configurable) default or pass directives: Valid directives are - -\starttabulate -\NC \bf conversion \NC \bf rendering \NC \NR -\HL -\NC \type{inverted} \NC the Frog jr, Kermit \NC \NR -\NC \type{invertedshort} \NC the Frog jr, K \NC \NR -\NC \type{normal} \NC Kermit, the Frog, jr \NC \NR -\NC \type{normalshort} \NC K, the Frog, jr \NC \NR -\stoptabulate - -The list itself is not a list in the sense of a regular \CONTEXT\ structure related -list. We do use the list mechanism to keep track of used entries but that is mostly -because we can then reuse filtering mechanisms. The actual rendering of a reference -and entry runs on top of so called constructions (other examples of constructions are -descriptions, enumerations and notes). - -\showsetup[setupbtxlist] - -You need to be aware what command is used to achieve the desired result. For instance, -in order to put parentheses around a number reference you say: - -\starttyping -\setupbtxlistvariant - [num] - [left=(, - right=)] -\stoptyping - -If you want automated width calculations, the following does the trick: - -\starttyping -\setupbtxrendering - [standard] - [width=auto] -\stoptyping - -but if you want to control it yourself you say something: - -\starttyping -\setupbtxrendering - [width=none] - -\setupbtxlist - [standard] - [width=3cm, - distance=\emwidth, - color=red, - headcolor=blue, - headalign=flushright] -\stoptyping - -In most cases the defaults will work out fine. - -\stopchapter - -\startchapter[title=Citations] - -Citations are references to bibliographic entries that normally show up in lists -someplace in the document: at the end of a chapter, in an appendix, at the end of -an article, etc. We discussed the rendering of these lists in the previous chapter. -A citation is normally pretty short as its main purpose is to refer uniquely to a more -detailed description. But, there are several ways to refer, which is why the citation -subsystem is configurable and extensible. Just look at the following commands: - -\startbuffer -\cite[author][example::demo-003] -\cite[authoryear][example::demo-003] -\cite[authoryears][example::demo-003] -\cite[author][example::demo-003,demo-004] -\cite[authoryear][example::demo-003,demo-004] -\cite[authoryears][example::demo-003,demo-004] -\cite[author][example::demo-004,demo-003] -\cite[authoryear][example::demo-004,demo-003] -\cite[authoryears][example::demo-004,demo-003] -\stopbuffer - -\typebuffer - -\startlines \getbuffer \stoplines - -The first argument is optional. -% What is the default? How can one set this up? - -\showsetup[cite] - -You can tune the way a citation shows up: - -\startbuffer -\setupbtxcitevariant[author] [sorttype=author,color=darkyellow] -\setupbtxcitevariant[authoryear] [sorttype=author,color=darkyellow] -\setupbtxcitevariant[authoryears][sorttype=author,color=darkyellow] - -\cite[author][example::demo-004,demo-003] -\cite[authoryear][example::demo-004,demo-003] -\cite[authoryears][example::demo-004,demo-003] -\stopbuffer - -\typebuffer - -Here we sort the authors and color the citation: - -\startlines \getbuffer \stoplines - -For reasons of backward compatibility the \type {\cite} command is a bit picky -about spaces between the two arguments, of which the first is optional. This is -a consequence of allowing its use with the key specified between curly brackets -as is the traditional practice. (We do encourage users to adopt the more -coherent \CONTEXT\ syntax by using square brackets for keywords and reserving -curly brackets to regroup text to be typeset.) -% Just how is it picky? - -The \type {\citation} command is synonymous but is more flexible with respect to -spacing of its arguments: - -\starttyping -\citation[author] [example::demo-004,demo-003] -\citation[authoryear] [example::demo-004,demo-003] -\citation[authoryears][example::demo-004,demo-003] -\stoptyping - -% The first argument of cite and citation is optional. What is the default and how does one set it? - -There is a whole bunch of cite options and more can be easily defined. - -\startluacode -local variants = publications.tracers.citevariants - -context.starttabulate { "|l|p|" } - context.NC() context.bold("key") - context.NC() context.bold("rendering") - context.NC() context.NR() context.FL() - for i=1,#variants do - local variant = variants[i] - context.NC() context.type(variant) - context.NC() context.citation( { variant }, { "example::demo-005" }) - context.NC() context.NR() - end -context.stoptabulate() -\stopluacode - -Because we are dealing with database input and because we generally need to -manipulate entries, much of the work is delegated to \LUA. This makes it easier -to maintain and extend the code. Of course \TEX\ still does the rendering. The -typographic details are controlled by parameters but not all are used in all -variants. As with most \CONTEXT\ commands, it starts out with a general setup -command: - -\showsetup[setupbtxcitevariant] - -On top of that we can define instances that inherit either from a given parent or -from the topmost setup. - -\showsetup[definebtxcitevariant] - -% The default values are: - -% \showrootvalues[btxcitevariant] - -But, specific variants can have them overloaded: - -% \showinstancevalues[setupbtxcitevariant][author] -% \showinstancevalues[setupbtxcitevariant][authornum] - -\startluacode - local variants = publications.tracers.citevariants - - for i=1,#variants do - context.showinstancevalues( { "btxcitevariant" }, { variants[i] }) - end -\stopluacode - -A citation variant is defined in several steps and if you really want to know -the dirty details, you should look into the \type {publ-imp-*.mkiv} files. Here -we stick to the concept. - -\starttyping -\startsetups btx:cite:author - \btxcitevariant{author} -\stopsetups -\stoptyping - -You can overload such setups if needed, but that only makes sense when you cannot -configure the rendering with parameters. The \type {\btxcitevariant} command is -one of the build in accessors and it calls out to \LUA\ where more complex -manipulation takes place if needed. If no manipulation is known, the field with -the same name (if found) will be flushed. A command like \type {\btxcitevariant} -assumes that a dataset and specific tag has been set. This is normally done in -the wrapper macros, like \type {\cite}. For special purposes you can use these -commands - -\starttyping -\setbtxdataset[example] -\setbtxentry[hh2013] -\stoptyping - -But don't expect too much support for such low level rendering control. - -Unless you use \type {criterium=all} only publications that are cited will end up -in the lists. You can force a citation into a list using \type {\usecitation}, for -example: - -\starttyping -\usecitation[example::demo-004,demo-003] -\stoptyping - -This command has two synonyms: \type {\nocite} and \type {\nocitation} so you can -choose whatever fits you best. - -\showsetup[nocite] - -\stopchapter - -\startchapter[title=The \LUA\ view] - -Because we manage data at the \LUA\ end it is tempting to access it there for -other purposes. This is fine as long as you keep in mind that aspects of the -implementation may change over time, although this is unlikely once the modules -become stable. - -The entries are collected in datasets and each set has a unique name. In this -document we have the set named \type {example}. A dataset table has several -fields, and probably the one of most interest is the \type {luadata} field. Each -entry in this table describes a publication: - -\startluacode - context.tocontext(publications.datasets.example.luadata["demo-001"]) -\stopluacode - -This is \type {publications.datasets.example.luadata["demo-001"]}. There can be -a companion entry in the parallel \type {details} table. - -\startluacode - context.tocontext(publications.datasets.example.details["demo-001"]) -\stopluacode - -These details are accessed as \type -{publications.datasets.example.details["demo-001"]} and by using a separate table -we can overload fields in the original entry without losing the original. - -You can loop over the entries using regular \LUA\ code combined with \MKIV\ -helpers: - -\startbuffer -local dataset = publications.datasets.example - -context.starttabulate { "|l|l|l|" } -for tag, entry in table.sortedhash(dataset.luadata) do - local detail = dataset.details[tag] or { } - context.NC() context.type(tag) - context.NC() context(detail.short) - context.NC() context(entry.title) - context.NC() context.NR() -end -context.stoptabulate() -\stopbuffer - -\typebuffer - -This results in: - -\ctxluabuffer - -You can manipulate a dataset after loading. Of course this assumes that you know -what kind of content you have and what you need for rendering. As example we -load a small dataset. - -\startbuffer -\definebtxdataset[drumming] -\usebtxdataset[drumming][mkiv-publications.lua] -\stopbuffer - -\typebuffer \getbuffer - -Because we're going to do some \LUA, we could also have loaded the dataset -with: - -\starttyping -publications.load("drumming","mkiv-publications.lua","lua") -\stoptyping - -The dataset has three entries: - -\typefile{mkiv-publications.lua} - -As you can see, we can have a subtitle. We will combine the title and subtitle -into one: - -\startbuffer -\startluacode -for tag, entry in next, publications.datasets.drumming.luadata do - if entry.subtitle then - if entry.title then - entry.title = entry.title .. ", " .. entry.subtitle - else - entry.title = entry.subtitle - end - entry.subtitle = nil - logs.report("btx","combining title and subtitle of entry tagged %a",tag) - end -end -\stopluacode -\stopbuffer - -\typebuffer \getbuffer - -We can now typeset the entries with: - -\startbuffer -\definebtxrendering[drumming][dataset=drumming,method=dataset] -\placebtxrendering[drumming] -\stopbuffer - -\typebuffer - -Because we just want to show the entries, and have no citations that force them -to be shown, we have to the \type {method} to \type {dataset}. \footnote {Gavin -Harrison is in my opinion one of the most creative, diverse and interesting -drummers of our time. It's also fascinating to watch him play and a welcome -distraction from writing code and manuals.} - -\blank \getbuffer \blank - -\stopchapter - -\startchapter[title=The \XML\ view] - -The \type {luadata} table can be converted into an \XML\ representation. This is -a follow up on earlier experiments with an \XML|-|only approach. I decided in the end -to stick to a \LUA\ approach and provide some simple \XML\ support in addition. - -Once a dataset is accessible as \XML\ tree, you can use the regular \type {\xml...} -commands. We start with loading a dataset, in this case from just one file. - -\startbuffer -\usebtxdataset[tugboat][tugboat.bib] -\stopbuffer - -\typebuffer \getbuffer - -The dataset has to be converted to \XML: - -\startbuffer -\convertbtxdatasettoxml[tugboat] -\stopbuffer - -\typebuffer \getbuffer - -The tree is now accessible by its root reference \type {btx:tugboat}. If we want simple -field access we can use a few setups: - -\startbuffer -\startxmlsetups btx:initialize - \xmlsetsetup{#1}{bibtex|entry|field}{btx:*} - \xmlmain{#1} -\stopxmlsetups - -\startxmlsetups btx:field - \xmlflushcontext{#1} -\stopxmlsetups - -\xmlsetup{btx:tugboat}{btx:initialize} -\stopbuffer - -\typebuffer \getbuffer - -The two setups are predefined in the core already, but you might want to change them. They are -applied in for instance: - -\startbuffer -\starttabulate[|||] - \NC \type {tag} \NC \xmlfirst {btx:tugboat} - {/bibtex/entry[string.find(@tag,'Hagen')]/attribute('tag')} - \NC \NR - \NC \type {title} \NC \xmlfirst {btx:tugboat} - {/bibtex/entry[string.find(@tag,'Hagen')]/field[@name='title']} - \NC \NR -\stoptabulate -\stopbuffer - -\typebuffer \getbuffer - -\startbuffer -\startxmlsetups btx:demo - \xmlcommand - {#1} - {/bibtex/entry[string.find(@tag,'Hagen')][1]}{btx:table} -\stopxmlsetups - -\startxmlsetups btx:table -\starttabulate[|||] - \NC \type {tag} \NC \xmlatt{#1}{tag} \NC \NR - \NC \type {title} \NC \xmlfirst{#1}{/field[@name='title']} \NC \NR -\stoptabulate -\stopxmlsetups - -\xmlsetup{btx:tugboat}{btx:demo} -\stopbuffer - -\typebuffer \getbuffer - -Here is another example: - -\startbuffer -\startxmlsetups btx:row - \NC \xmlatt{#1}{tag} - \NC \xmlfirst{#1}{/field[@name='title']} - \NC \NR -\stopxmlsetups - -\startxmlsetups btx:demo - \xmlfilter {#1} { - /bibtex - /entry[@category='article'] - /field[@name='author' and (find(text(),'Knuth') or find(text(),'DEK'))] - /../command(btx:row) - } -\stopxmlsetups - -\starttabulate[|||] - \xmlsetup{btx:tugboat}{btx:demo} -\stoptabulate -\stopbuffer - -\typebuffer \getbuffer - -A more extensive example is the following. Of course this assumes that you -know what \XML\ support mechanisms and macros are available. - -\startbuffer -\startxmlsetups btx:getkeys - \xmladdsortentry{btx}{#1}{\xmlfilter{#1}{/field[@name='author']/text()}} - \xmladdsortentry{btx}{#1}{\xmlfilter{#1}{/field[@name='year' ]/text()}} - \xmladdsortentry{btx}{#1}{\xmlatt{#1}{tag}} -\stopxmlsetups - -\startxmlsetups btx:sorter - \xmlresetsorter{btx} - % \xmlfilter{#1}{entry/command(btx:getkeys)} - \xmlfilter{#1}{ - /bibtex - /entry[@category='article'] - /field[@name='author' and find(text(),'Knuth')] - /../command(btx:getkeys)} - \xmlsortentries{btx} - \starttabulate[||||] - \xmlflushsorter{btx}{btx:entry:flush} - \stoptabulate -\stopxmlsetups - -\startxmlsetups btx:entry:flush - \NC \xmlfilter{#1}{/field[@name='year' ]/context()} - \NC \xmlatt{#1}{tag} - \NC \xmlfilter{#1}{/field[@name='author']/context()} - \NC \NR -\stopxmlsetups - -\xmlsetup{btx:tugboat}{btx:sorter} -\stopbuffer - -\typebuffer \getbuffer - -The original data is stored in a \LUA\ table, hashed by tag. Starting with \LUA\ 5.2 -each run of \LUA\ gets a different ordering of such a hash. In older versions, when you -looped over a hash, the order was undefined, but the same as long as you used the same -binary. This had the advantage that successive runs, something we often have in document -processing gave consistent results. In today's \LUA\ we need to do much more sorting of -hashes before we loop, especially when we save multi||pass data. It is for this reason -that the \XML\ tree is sorted by hash key by default. That way lookups (especially -the first of a set) give consistent outcomes. - -\stopchapter - -\startchapter[title=Standards] - -The rendering of bibliographic entries is often standardized and prescribed by -the publisher. If you submit an article to a journal, normally it will be -reformatted (or even re|-|keyed) and the rendering will happen at the publishers -end. In that case it may not matter how entries were rendered when writing the -publication, because the publisher will do it his or her way. -This means that most users probably will stick to the standard \APA\ rules and for -them we provide some configuration. Because we use setups it is easy to overload -specifics. If you really want to tweak, best look in the files that deal with it. - -Many standards exist and support for other renderings may be added to the core. -Interested users are invited to develop and to test alternate standard renderings -according to their needs. - -Todo: maybe a list of categories and fields. - -\stopchapter - -\startchapter[title=Cleaning up] - -Although the \BIBTEX\ format is reasonably well defined, in practice there are -many ways to organize the data. For instance, one can use predefined string -constants that get used (either or not combined with other strings) later on. A string -can be enclosed in curly braces or double quotes. The strings can contain \TEX\ commands -but these are not standardized. The databases often have somewhat complex -ways to deal with special characters and the use of braces in their definition is also -not normalized. - -The most complex to deal with are the fields that contain names of people. At some point it -might be needed to split a combination of names into individual ones that then get split into -title, first name, optional inbetweens, surname(s) and additional: \type {Prof. Dr. Alfred -B. C. von Kwik Kwak Jr. II and P. Q. Olet} is just one example of this. The convention seems -to be not to use commas but \type {and} to separate names (often each name will be specified -as lastname, firstname). - -We don't see it as challenge nor as a duty to support all kinds of messy definitions. Of -course we try to be somewhat tolerant, but you will be sure to get better results if you -use nicely setup, consistent databases. - -Todo: maybe some examples of bad. - -\stopchapter - -\startchapter[title=Transition] - -In the original bibliography support module usage was as follows (example taken -from the contextgarden wiki): - -\starttyping -% engine=pdftex - -\usemodule[bib] -\usemodule[bibltx] - -\setupbibtex - [database=xampl] - -\setuppublications - [numbering=yes] - -\starttext - As \cite [article-full] already indicated, bibtex is a \LATEX||centric - program. - - \completepublications -\stoptext -\stoptyping - -For \MKIV\ the modules were partly rewritten and ended up in the core so the two -{\usemodule} commands were no longer needed. The overhead associated with the -automatic loading of the bibliography macros can be neglected these days, so -standardized modules such as \type {bib} are all being moved to the core and do -not need to be explicitly loaded. - -The first \type {\setupbibtex} command in this example is needed to bootstrap -the process: it tells what database has to be processed by \BIBTEX\ between -runs. The second \type {\setuppublications} command is optional. Each citation -(tagged with \type {\cite}) ends up in the list of publications. - -In the new approach we no longer use \BIBTEX so we don't need to setup \BIBTEX. -Instead we define dataset(s). We also no longer set up publications with one -command, but have split that up in rendering-, list-, and cite|-|variants. The -basic \type {\cite} command remains. The above example becomes: - -\starttyping -\definebtxdataset - [document] - -\usebtxdataset - [document] - [mybibfile.bib] - -\definebtxrendering - [document] - -\setupbtxrendering - [document] - [numbering=yes] - -\starttext - As \cite [article-full] already indicated, bibtex is a \LATEX||centric - program. - - \completebtxrendering[document] -\stoptext -\stoptyping - -So, we have a few more commands to set up things. If you intend to use just a -single dataset and rendering, the above preamble can be simplified to: - -\starttyping -\usebtxdataset - [mybibfile.bib] - -\setupbtxrendering - [numbering=yes] -\stoptyping - -But keep in mind that compared to the old \MKII\ derived method we have moved -some of the options to the rendering, list and cite setup variants. - -Another difference is now the use of lists. When you define a rendering, you -also define a list. However, all entries are collected in a common list tagged -\type {btx}. Although you will normally configure a rendering you can still set -some properties of lists, but in that case you need to prefix the list -identifier. In the case of the above example this is \type {btx:document}. - -\stopchapter - -\startchapter[title=\MLBIBTEX] - -Todo: how to plug in \MLBIBTEX\ for sorting and other advanced operations. - -\stopchapter - -\startchapter[title=Extensions] - -As \TEX\ and \LUA\ are both open and accessible in \CONTEXT\ it is possible to -extend the functionality of the bibliography related code. For instance, you can add -extra loaders. - -\starttyping -function publications.loaders.myformat(dataset,filename) - local t = { } - -- Load data from 'filename' and convert it to a Lua table 't' with - -- the key as hash entry and fields conforming the luadata table - -- format. - loaders.lua(dataset,t) -end -\stoptyping - -This then permits loading a database (into a dataset) with the command: - -\starttyping -\usebtxdataset[standard][myfile.myformat] -\stoptyping - -The \type {myformat} suffix is recognized automatically. If you want to use another -suffix, you can do this: - -\starttyping -\usebtxdataset[standard][myformat::myfile.txt] -\stoptyping - -\stopchapter - -\startchapter[title=Notes] - -The move from external \BIBTEX\ processing to internal processing has the -advantage that we stay within the same run. In the traditional approach we had -roughly the following steps: - -\startitemize[packed] -\startitem the first run information is collected and written to file \stopitem -\startitem after that run the \BIBTEX\ program converts that file to another one \stopitem -\startitem successive runs use that data for references and producing lists \stopitem -\stopitemize - -In the \MKIV\ approach the bibliographic database is loaded in memory each run -and processing also happens each run. On paper this looks less efficient but as -\LUA\ is quite fast, in practice performance is much better. - -Probably most demanding is the treatment of authors as we have to analyze names, -split multiple authors and reassemble firstnames, vons, surnames and juniors. -When we sort by author sorting vectors have to be made which also has a penalty. -However, in practice the user will not notice a performance degradation. We did -some tests with a list of 500.000 authors, sorted them and typeset them as list -(producing some 5400 dense pages in a small font and with small margins). This is -typical one of these cases where using \LUAJITTEX\ saves quite time. On my -machine it took just over 100 seconds to get this done. Unfortunately not all -operating systems performed equally well: 32 bit versions worked fine, but 64 bit -\LINUX\ either crashed (stalled) the machine or ran out of memory rather fast, -while \MACOSX\ and \WINDOWS\ performed fine. In practice you will never run into -this, unless you produce massive amounts of bibliographic entries. \LUAJIT\ has -some benefits but also some drawbacks. - -\stopchapter - -\stopbodymatter - -\stoptext - -Todo: - -\setuplabeltext[en][reprint=reprint] -\setuplabeltext[de][reprint=Nachdruck] - -note = {\labeltext{reprint} 2004} - diff --git a/doc/context/manuals/allkind/publications-en.xml b/doc/context/manuals/allkind/publications-en.xml deleted file mode 100644 index ea577ccf4..000000000 --- a/doc/context/manuals/allkind/publications-en.xml +++ /dev/null @@ -1,369 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- bibliographies --> - -<cd:interface xmlns:cd="http://www.pragma-ade.com/commands" name="publications" language="en" version="2013.12.22"> - - <!-- datasets --> - - <cd:command name="setupbtxdataset" file="publ-ini.mkiv" category="publications" hash="btxdataset"> - <cd:sequence> - <cd:string value="setupbtxdataset"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1" optional="yes"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:assignments n="2" optional="yes"> - <!-- todo --> - </cd:assignments> - </cd:arguments> - </cd:command> - - <cd:command name="definebtxdataset" file="publ-ini.mkiv" category="publications" hash="btxdataset"> - <cd:sequence> - <cd:string value="definebtxdataset"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:assignments n="2" optional="yes"> - <cd:inherit name="setupbtxdataset" n="2"/> - </cd:assignments> - </cd:arguments> - </cd:command> - - <cd:command name="usebtxdataset" file="publ-ini.mkiv" category="publications" hash="btxdataset"> - <cd:sequence> - <cd:string value="usebtxdataset"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:keywords n="2"> - <cd:constant type="cd:file"/> - </cd:keywords> - </cd:arguments> - </cd:command> - - <!-- rendering --> - - <cd:command name="setupbtxrendering" file="publ-ini.mkiv" category="publications" hash="btxrendering"> - <cd:sequence> - <cd:string value="setupbtxrendering"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1" optional="yes"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:assignments n="2"> - <cd:parameter name="alternative"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="dataset"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="setups"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="method"> - <cd:constant type="local"/> - <cd:constant type="global"/> - <cd:constant type="none"/> - <cd:constant type="force"/> - </cd:parameter> - <cd:parameter name="sorttype"> - <cd:constant type="short"/> - <cd:constant type="reference"/> - <cd:constant type="dataset"/> - <cd:constant type="default"/> - </cd:parameter> - <cd:parameter name="criterium"> - <cd:constant type="cd:text"/> <!-- todo --> - </cd:parameter> - <cd:parameter name="refcommand"> - <cd:constant type="cd:text"/> <!-- todo --> - </cd:parameter> - <cd:parameter name="numbering"> - <cd:constant type="yes"/> - <cd:constant type="cite"/> - </cd:parameter> - <cd:parameter name="width"> - <cd:constant type="cd:dimension"/> - <cd:constant type="auto"/> - </cd:parameter> - <cd:parameter name="distance"> - <cd:constant type="cd:dimension"/> - </cd:parameter> - <cd:parameter name="continue"> - <cd:constant type="yes"/> - <cd:constant type="no"/> - </cd:parameter> - </cd:assignments> - </cd:arguments> - </cd:command> - - <cd:command name="definebtxrendering" file="publ-ini.mkiv" category="publications" hash="btxrendering"> - <cd:sequence> - <cd:string value="definebtxrendering"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:keywords n="2" optional="yes"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:assignments n="3" optional="yes"> - <cd:inherit name="setupbtxrendering" n="2"/> - </cd:assignments> - </cd:arguments> - </cd:command> - - <cd:command name="placebtxrendering" file="publ-ini.mkiv" category="publications" hash="btxrendering"> - <cd:sequence> - <cd:string value="placebtxrendering"/> - </cd:sequence> - </cd:command> - - <!-- lists --> - - <cd:command name="setupbtxlistvariant" file="publ-ini.mkiv" category="publications" hash="btxlistvariant"> - <cd:sequence> - <cd:string value="setupbtxlistvariant"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1" optional="yes"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:assignments n="2"> - <cd:parameter name="namesep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="lastnamesep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="finalnamesep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="firstnamesep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="juniorsep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="vonsep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="surnamesep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="surnamejuniorsep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="juniorjuniorsep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="surnamefirstnamesep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="surnameinitialsep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="etallimit"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="etaldisplay"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="etaltext"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="monthconversion"> - <cd:constant type="number"/> - <cd:constant type="month"/> - <cd:constant type="month:mnem"/> - </cd:parameter> - <cd:parameter name="authorconversion"> - <cd:constant type="normal"/> - <cd:constant type="inverted"/> - <cd:constant type="normalshort"/> - <cd:constant type="invertedshort"/> - </cd:parameter> - </cd:assignments> - </cd:arguments> - </cd:command> - - <cd:command name="definebtxlistvariant" file="publ-ini.mkiv" category="publications" hash="btxlistvariant"> - <cd:sequence> - <cd:string value="definebtxlistvariant"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1"> - <cd:constant type="cd:name"/> - </cd:keywords> - </cd:arguments> - </cd:command> - - <!-- variants --> - - <cd:command name="setupbtxcitevariant" file="publ-ini.mkiv" category="publications" hash="btxcitevariant"> - <cd:sequence> - <cd:string value="setupbtxcitevariant"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1" optional="yes"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:assignments n="2"> - <cd:parameter name="alternative"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="setups"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="interaction"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="andtext"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="otherstext"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="compress"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="putsep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="lastputsep"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="inbetween"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="right"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="middle"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="left"> - <cd:constant type="cd:text"/> - </cd:parameter> - </cd:assignments> - </cd:arguments> - </cd:command> - - <cd:command name="definebtxcitevariant" file="publ-ini.mkiv" category="publications" hash="btxcitevariant"> - <cd:sequence> - <cd:string value="definebtxcitevariant"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:keywords n="2" optional="yes"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:assignments n="3" optional="yes"> - <cd:inherit name="setupbtxvariant" n="3"/> - </cd:assignments> - </cd:arguments> - </cd:command> - - <!-- refering --> - - <cd:command name="cite" file="publ-ini.mkiv" category="publications"> - <cd:sequence> - <cd:string value="cite"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1" optional="yes"> - <cd:constant type="cd:name"/> - </cd:keywords> - <cd:keywords n="2"> - <cd:constant type="cd:name"/> - </cd:keywords> - </cd:arguments> - </cd:command> - - <cd:command name="nocite" file="publ-ini.mkiv" category="publications"> - <cd:sequence> - <cd:string value="nocite"/> - </cd:sequence> - <cd:arguments> - <cd:keywords n="1"> - <cd:constant type="cd:name"/> - </cd:keywords> - </cd:arguments> - </cd:command> - - <!-- list entries --> - - - <cd:command name="setupbtxlist" file="publ-ini.mkiv" category="publications" hash="btxlist"> - <cd:sequence> - <cd:string value="setupbtxlist"/> - </cd:sequence> - <cd:arguments> - <cd:assignments n="1"> - <cd:parameter name="alternative"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="style"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="color"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="headstyle"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="headcolor"> - <cd:constant type="cd:text"/> - </cd:parameter> - <cd:parameter name="width"> - <cd:constant type="cd:dimension"/> - </cd:parameter> - <cd:parameter name="distance"> - <cd:constant type="cd:dimension"/> - </cd:parameter> - <cd:parameter name="hang"> - <cd:constant type="cd:number"/> - </cd:parameter> - <cd:parameter name="align"> - <cd:resolve name="align"/> - </cd:parameter> - <cd:parameter name="headalign"> - <cd:resolve name="symalign"/> - </cd:parameter> - <cd:parameter name="margin"> - <cd:constant type="cd:yes"/> - <cd:constant type="cd:no"/> - </cd:parameter> - <cd:parameter name="before"> - <cd:constant type="cd:command" default="\blank"/> - </cd:parameter> - <cd:parameter name="inbetween"> - <cd:constant type="cd:command"/> - </cd:parameter> - <cd:parameter name="after"> - <cd:constant type="cd:command" default="\blank"/> - </cd:parameter> - <cd:parameter name="display"> - <cd:constant type="cd:yes"/> - <cd:constant type="cd:no"/> - </cd:parameter> - <cd:parameter name="command"> - <cd:constant type="cd:command"/> - </cd:parameter> - </cd:assignments> - </cd:arguments> - </cd:command> - - -</cd:interface> diff --git a/doc/context/scripts/mkiv/mtx-bibtex.html b/doc/context/scripts/mkiv/mtx-bibtex.html deleted file mode 100644 index ba1591b4b..000000000 --- a/doc/context/scripts/mkiv/mtx-bibtex.html +++ /dev/null @@ -1,53 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - -<!-- compare with lmx framework variant --> - -<!-- - filename : context-base.xml - comment : companion to mtx-server-ctx-startup.tex - author : Hans Hagen, PRAGMA-ADE, Hasselt NL - copyright: PRAGMA ADE / ConTeXt Development Team - license : see context related readme files ---> - -<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> - <head> - <title>bibtex helpers</title> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> - <style type="text/css"> - body { color: #FFFFFF; background-color: #808080; font-family: optima, verdana, futura, "lucida sans", arial, geneva, helvetica, sans; font-size: 12px; line-height: 18px; } a:link, a:active, a:visited { color: #FFFFFF; } a.dir-view:link, a.dir-view:active, a.dir-view:visited { color: #FFFFFF; text-decoration: underline; } .valid { color: #00FF00; } .invalid { color: #FF0000; } button, .commonlink, .smallbutton { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; border-color: #7F7F7F; border-style: solid; border-width: .125ex; background-color: #FFFFFF; padding: .5ex; } .smallbutton { width: 1em; } a.commonlink:link, a.commonlink:active, a.commonlink:visited, a.smalllink:link, a.smalllink:active, a.smalllink:visited { font-weight: bold; font-size: 12px; text-decoration: none; color: #000000; } h1, .title { font-style: normal; font-weight: normal; font-size: 18px; line-height: 18px; margin-bottom: 20px; } h2, .subtitle { font-style: normal; font-weight: normal; font-size: 12px; margin-top: 18px; margin-bottom: 18px; } table { line-height: 18px; font-size: 12px; margin: 0; } th { font-weight: bold; text-align: left; padding-bottom: 6px; } .tc { font-weight: bold; text-align: left; } p, li { max-width: 60em; } .empty-line { margin-top: 4px; } .more-room { margin-right: 1.5em; } .much-more-room { margin-right: 3em; } #main { position: absolute; left: 10%; top: 10%; right: 10%; bottom: 10%; z-index: 2; width: 80%; height: 80%; padding: 0%; margin: 0%; overflow: auto; border-style: none; border-width: 0; background-color: #3F3F3F; } #main-settings { margin: 12px; x_max-width: 60em; line-height: 18px; font-size: 12px; } #left { position: absolute; top : 10%; left: 0%; bottom: 0%; right: 90%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; } #right { position: absolute; top : 0%; left: 90%; bottom: 10%; right: 0%; z-index: 1; width: 10%; height: 90%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #4F6F6F; _margin-left: -15px; } #bottom { position: absolute; left: 10%; right: 0%; top: 90%; bottom: 0%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top { position: absolute; left: 0%; right: 10%; top: 0%; bottom: 90%; z-index: 1; width: 90%; height: 10%; padding: 0%; margin: 0%; font-size: 16px; border-style: none; border-width: 0; background-color: #6F6F8F; } #top-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #top-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: right; vertical-align: middle; } #bottom-one { position: absolute; bottom: 50%; width: 100%; buggedheight: 100%; } #bottom-two { position: relative; margin-bottom: -9px; margin-left: 12px; margin-right: 12px; line-height: 18px; text-align: left; vertical-align: middle; } #left-one { position: absolute; width: 100%; buggedheight: 100%; } #left-two { position: relative; margin-top: 12px; line-height: 18px; text-align: center; vertical-align: top; } #right-one { display: table; height: 100%; width: 100%; } #right-two { display: table-row; height: 100%; width: 100%; } #right-three { display: table-cell; width: 100%; vertical-align: bottom; _position: absolute; _top: 100%; } #right-four { text-align: center; margin-bottom: 2ex; _position: relative; _top: -100%; } #more-top { position: absolute; top: 0%; left: 90%; bottom: 90%; right: 0%; z-index: 3; width: 10%; height: 10%; padding: 0%; margin: 0%; border-style: none; border-width: 0; } #more-top-settings { text-align: center; } #more-right-settings { margin-right: 12px; margin-left: 12px; line-height: 18px; font-size: 10px; text-align: center; } #right-safari { _display: table; width: 100%; height: 100%; } - </style> - <style type="text/css"> - </style> - </head> - <body> - <div id="top"> <div id="top-one"> - <div id="top-two">bibtex helpers </div> - </div> - </div> - <div id="bottom"> <div id="bottom-one"> - <div id="bottom-two">wiki: http://contextgarden.net | mail: ntg-context@ntg.nl | website: http://www.pragma-ade.nl</div> - </div> - </div> - <div id="left"></div> - <div id="right"></div> - <div id="main"> - <div id='main-settings'> - <h1>Command line options</h1> -<table> - <tr><th style="width: 10em">flag</th><th style="width: 8em">value</th><th>description</th></tr> - <tr><th/><td/><td/></tr> - <tr><th>--toxml</th><td></td><td>convert bibtex database(s) to xml</td></tr> - <tr><th>--tolua</th><td></td><td>convert bibtex database(s) to lua</td></tr> - </table> -<br/> -<h1>Example</h1> -<tt>mtxrun --script bibtex --tolua bibl-001.bib</tt> -<br/><tt>mtxrun --script bibtex --tolua --simple bibl-001.bib</tt> -<br/><tt>mtxrun --script bibtex --toxml bibl-001.bib bibl-002.bib bibl-003.bib biblio.xml</tt> -<br/><br/> </div> - </div> - </body> - </html> diff --git a/doc/context/scripts/mkiv/mtx-bibtex.man b/doc/context/scripts/mkiv/mtx-bibtex.man deleted file mode 100644 index cedf41b8b..000000000 --- a/doc/context/scripts/mkiv/mtx-bibtex.man +++ /dev/null @@ -1,30 +0,0 @@ -.TH "mtx-bibtex" "1" "01-01-2014" "version 1.00" "bibtex helpers" -.SH NAME -.B mtx-bibtex -.SH SYNOPSIS -.B mtxrun --script bibtex [ -.I OPTIONS ... -.B ] [ -.I FILENAMES -.B ] -.SH DESCRIPTION -.B bibtex helpers -.SH OPTIONS -.TP -.B --toxml -convert bibtex database(s) to xml -.TP -.B --tolua -convert bibtex database(s) to lua -.SH AUTHOR -More information about ConTeXt and the tools that come with it can be found at: - - -.B "maillist:" -ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context - -.B "webpage:" -http://www.pragma-ade.nl / http://tex.aanhet.net - -.B "wiki:" -http://contextgarden.net diff --git a/doc/context/scripts/mkiv/mtx-bibtex.xml b/doc/context/scripts/mkiv/mtx-bibtex.xml deleted file mode 100644 index b33e1809c..000000000 --- a/doc/context/scripts/mkiv/mtx-bibtex.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-bibtex</entry> - <entry name="detail">bibtex helpers</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="toxml"><short>convert bibtex database(s) to xml</short></flag> - <flag name="tolua"><short>convert bibtex database(s) to lua</short></flag> - </subcategory> - </category> - </flags> - <examples> - <category> - <title>Example</title> - <subcategory> - <example><command>mtxrun --script bibtex --tolua bibl-001.bib</command></example> - <example><command>mtxrun --script bibtex --tolua --simple bibl-001.bib</command></example> - <example><command>mtxrun --script bibtex --toxml bibl-001.bib bibl-002.bib bibl-003.bib biblio.xml</command></example> - </subcategory> - </category> - </examples> -</application> diff --git a/metapost/context/base/mp-base.mpii b/metapost/context/base/mp-base.mpii index 7af4bc436..0f8104447 100644 --- a/metapost/context/base/mp-base.mpii +++ b/metapost/context/base/mp-base.mpii @@ -110,15 +110,12 @@ transform identity; for z=origin,right,up: z transformed identity = z; endfor % color constants -color black, white, red, green, blue, cyan, magenta, yellow, background; +color black, white, red, green, blue, background; black = (0,0,0); white = (1,1,1); red = (1,0,0); green = (0,1,0); blue = (0,0,1); -cyan = (0,1,1); -magenta = (1,0,1); -yellow = (1,1,0); background = white; % The user can reset this % color part selection for within @@ -363,17 +360,9 @@ enddef; def filldraw expr c = addto currentpicture contour c withpen currentpen _op_ enddef; -% def drawdot expr z = -% addto currentpicture contour makepath currentpen shifted z -% _op_ enddef; - -def drawdot expr p = - if pair p : - addto currentpicture doublepath p withpen currentpen _op_ - else : - errmessage("drawdot only accepts a pair expression") - fi -enddef ; +def drawdot expr z = + addto currentpicture contour makepath currentpen shifted z + _op_ enddef; def unfill expr c = fill c withcolor background enddef; def undraw expr p = draw p withcolor background enddef; diff --git a/metapost/context/base/mp-base.mpiv b/metapost/context/base/mp-base.mpiv index 0b655ef47..2887cc462 100644 --- a/metapost/context/base/mp-base.mpiv +++ b/metapost/context/base/mp-base.mpiv @@ -323,7 +323,7 @@ primarydef w dotprod z = enddef ; primarydef x**y = - if y = 2 : + if y=2 : x*x else : takepower y of x @@ -348,46 +348,11 @@ def takepower expr y of x = endfor fi else : - hide(errmessage "Undefined power: " & decimal x & "**" & decimal y) + hide(errmessage "Undefined power: " & decimal x&"**"&decimal y) fi fi enddef ; -% for big number systems: -% -% primarydef x**y = -% if y = 1 : -% x -% elseif y = 2 : -% x*x -% elseif y = 3 : -% x*x*x -% else : -% takepower y of x -% fi -% enddef ; -% -% vardef takepower expr y of x = -% if (x=0) and (y>0) : -% 0 -% else : -% 1 -% if y = floor y : -% if y >= 0 : -% for n=1 upto y : -% *x -% endfor -% else : -% for n=-1 downto y : -% /x -% endfor -% fi -% else : -% hide(errmessage "Undefined power: " & decimal x & "**" & decimal y) -% fi -% fi -% enddef ; - vardef direction expr t of p = postcontrol t of p - precontrol t of p enddef ; @@ -629,36 +594,8 @@ def filldraw expr c = addto currentpicture contour c withpen currentpen _op_ enddef ; -% def drawdot expr z = -% addto currentpicture contour makepath currentpen shifted z _op_ -% enddef ; -% -% testcase DEK: -% -% for j=1 upto 9 : -% pickup pencircle xscaled .4 yscaled .2 ; -% drawdot (10j,0) withpen pencircle xscaled .5j yscaled .25j rotated 45 ; -% pickup pencircle xscaled .5j yscaled .25j rotated 45 ; -% drawdot (10j,10); -% endfor ; -% -% or: -% -%\startMPpage -% -% def drawdot expr z = -% addto currentpicture contour (makepath currentpen shifted z) _op_ -% enddef; -% -% drawdot origin shifted (0,-3cm) withpen pencircle scaled 2cm ; -% pickup pencircle scaled 2cm ; drawdot origin withcolor red ; - -def drawdot expr p = - if pair p : - addto currentpicture doublepath p withpen currentpen _op_ - else : - errmessage("drawdot only accepts a pair expression") - fi +def drawdot expr z = + addto currentpicture contour makepath currentpen shifted z _op_ enddef ; def unfill expr c = fill c withcolor background enddef ; diff --git a/metapost/context/base/mp-grap.mpiv b/metapost/context/base/mp-grap.mpiv index 6d69c0b1e..417bfbe69 100644 --- a/metapost/context/base/mp-grap.mpiv +++ b/metapost/context/base/mp-grap.mpiv @@ -52,11 +52,11 @@ fi % endgraph end of graph--the result is a picture % option `plot <picture>' draws picture at each path knot, turns off pen -% graph_template.<tickcmd> template paths for tick marks and grid lines +% Gtemplate.<tickcmd> template paths for tick marks and grid lines % graph_margin_fraction.low, % graph_margin_fraction.high fractions determining margins when no setrange -% graph_log_marks[], graph_lin_marks, graph_exp_marks loop text strings used by auto.<x or y> -% graph_minimum_number_of_marks, graph_log_minimum numeric parameters used by auto.<x or y> +% Glmarks[], Gumarks, Gemarks loop text strings used by auto.<x or y> +% Gmarks, Gminlog numeric parameters used by auto.<x or y> % Autoform is the format string used by autogrid % Autoform_X, Autoform_Y if defined, are used instead @@ -65,26 +65,22 @@ fi % with `graph_' % Depends on : - input string.mp % Private version of a few marith macros, fixed for double math... - -newinternal Mzero ; Mzero := -16384; % Anything at least this small is treated as zero -newinternal mlogten ; mlogten := mlog(10) ; -newinternal largestmantissa ; largestmantissa := 2**52 ; % internal double warningcheck -newinternal singleinfinity ; singleinfinity := 2**128 ; -newinternal doubleinfinity ; doubleinfinity := 2**1024 ; -Mzero := -largestmantissa ; % Note that we get arithmetic overflows if we set to -doubleinfinity +newinternal Mzero; Mzero := -16384; % Anything at least this small is treated as zero +newinternal mlogten ; mlogten := mlog(10) ; +newinternal singleinfinity ; singleinfinity := 2**128 ; +newinternal doubleinfinity ; doubleinfinity := 2**1024 ; +% Note that we get arithmetic overflows if we set to -doubleinfinity below. +% (but "only on odd days"...) % Safely convert a number to mlog form, trapping zero. - vardef graph_mlog primary x = if unknown x: whatever elseif x=0: Mzero else: mlog(abs x) fi enddef ; - vardef graph_exp primary x = if unknown x: whatever elseif x<=Mzero: 0 @@ -93,25 +89,21 @@ enddef ; % and add the following for utility/completeness % (replacing the definitions in mp-tool.mpiv). - vardef logten primary x = if unknown x: whatever elseif x=0: Mzero else: mlog(abs x)/mlog(10) fi enddef ; - vardef ln primary x = if unknown x: whatever elseif x=0: Mzero else: mlog(abs x)/256 fi enddef ; - vardef exp primary x = if unknown x: whatever elseif x<= Mzero: 0 else: (mexp 256)**x fi enddef ; - vardef powten primary x = if unknown x: whatever elseif x<= Mzero: 0 @@ -120,7 +112,6 @@ enddef ; % Convert x from mlog form into a pair whose xpart gives a mantissa and whose % ypart gives a power of ten. - vardef graph_Meform(expr x) = if x<=Mzero : origin else : @@ -131,7 +122,6 @@ vardef graph_Meform(expr x) = enddef ; % Modified from above. - vardef graph_Feform(expr x) = interim warningcheck :=0 ; if x=0 : origin @@ -156,7 +146,6 @@ def graph_suffix(suffix $) = % convert from x or y to X_ or Y_ enddef ; % New : - save graph_background ; color graph_background ; % if defined, fill the frame. save graph_close_file ; boolean graph_close_file ; graph_close_file = false ; @@ -211,20 +200,17 @@ enddef ; % user to alter the behavior of these macros. % Not very modifiable : log, linear, % graph_frame_pair_a, graph_frame_pair_b, graph_margin_pair -% Modifiable : graph_template.suffix, -% graph_log_marks[], graph_lin_marks, graph_exp_marks, -% graph_minimum_number_of_marks, -% graph_log_minimum, Autoform +% Modifiable : Gtemplate.suffix, Glmarks[], Gumarks, Gemarks, Gmarks, +% Gminlog, Autoform newinternal log, linear ; % coordinate system codes log :=1 ; linear :=2; - % note that mp-tool.mpiv defines log as log10. %%%%%%%%%%%%%%%%%%%%%% Coordinates : setcoords, setrange %%%%%%%%%%%%%%%%%%%%%% -% Graph-related user input is `user graph coordinates' as specified by arguments +% Graph-related usr input is `user graph coordinates' as specified by arguments % to setcoords. % `Internal graph coordinates' are used for graph_current_graph, graph_current_bb, Z_.low, Z_.high. % Their meaning depends on the appropriate component of Z_.graph_coordinate_type : @@ -241,15 +227,14 @@ vardef graph_set_default_bounds = % Set default Z_.low, Z_.high graph_margin_pair$ ; endfor enddef ; - pair graph_margin_pair.low, graph_margin_pair.high ; graph_margin_pair.high = -graph_margin_pair.low = (.00002,.00002) ; -% Set $, $$, $$$ so that shifting by $ then transforming by $$ and then $$$ maps -% the essential bounding box of graph_current_graph into (0,0)..Z_.graph_dimensions. -% The `essential bounding box' is either what Z_.low and Z_.high imply -% or the result of ignoring pen widths in graph_current_graph. +% Set $, $$, $$$ so that shifting by $ then transforming by $$ and then $$$ +% maps the essential bounding box of graph_current_graph into (0,0)..Z_.graph_dimensions. The +% `essential bounding box' is either what Z_.low and Z_.high imply or the +% result of ignoring pen widths in graph_current_graph. vardef graph_remap(suffix $,$$,$$$) = save p_ ; graph_set_default_bounds ; @@ -260,10 +245,10 @@ vardef graph_remap(suffix $,$$,$$$) = (Z_.high+$) transformed $$ = p_ ; p_ transformed $$$ = Z_.graph_dimensions ; enddef ; - graph_margin_fraction.low=-.07 ; % bbox fraction for default range start graph_margin_fraction.high=1.07 ; % bbox fraction for default range stop + def graph_with_pen_and_color(expr q) = withpen penpart q withcolor if colormodel q=1 : @@ -283,7 +268,7 @@ enddef ; % Pair o is the value of p that makes tp (0,0). This implements the trick % whereby using 1 instead of 0 for the width or height or the setbounds path % for a label picture suppresses shifting in x or y. - +% %vardef graph_picture_conversion@#(expr q, o)(text tp) = % save p ; % if stroked q : @@ -299,9 +284,8 @@ enddef ; % addto @# also q shifted ((tp)-llcorner q) ; % fi %enddef ; - +% % This new version makes gdraw clip the result to the window defined with setrange - vardef graph_picture_conversion@#(expr q, o)(text tp) = save p ; save do_clip, tp_clipped ; boolean do_clip ; do_clip := true ; @@ -331,11 +315,12 @@ enddef ; def graph_coordinate_multiplication(expr a,b) = (xpart a*xpart b, ypart a*ypart b) enddef ; + vardef graph_clear_bounds@# = numeric @#.low, @#.high ; enddef; + % Finalize anything drawn in the present coordinate system and set up a new % system as requested - vardef setcoords(expr tx, ty) = interim warningcheck :=0 ; if length graph_current_graph>0 : @@ -350,10 +335,10 @@ vardef setcoords(expr tx, ty) = X_.graph_coordinate_type := tx ; Y_.graph_coordinate_type := ty; enddef ; + % Set Z_.low and Z_.high to correspond to given range of user graph % coordinates. The text argument should be a sequence of pairs and/or strings % with 4 components in all. - vardef setrange(text t) = interim warningcheck :=0 ; save r_ ; r_=0; @@ -368,8 +353,8 @@ vardef setrange(text t) = endfor enddef ; -% @# is X_ or Y_ ; l and h are numeric or string +% @# is X_ or Y_ ; l and h are numeric or string vardef graph_set_bounds@#(expr l, h) = graph_clear_bounds@# ; if @#graph_coordinate_type>0 : @@ -397,12 +382,15 @@ vardef graph_set_bounds@#(expr l, h) = fi enddef ; + + + + %%%%%%%%%%%%%%%%%%%%%%%%% Converting path coordinates %%%%%%%%%%%%%%%%%%%%%%%%% % Find the result of scanning path p and using macros tx and ty to adjust the % x and y parts of each coordinate pair. Boolean parameter c tells whether to % force the result to be polygonal. - vardef graph_scan_path(expr p, c)(suffix tx, ty) = if (str tx="") and (str ty="") : p else : @@ -421,11 +409,10 @@ vardef graph_scan_path(expr p, c)(suffix tx, ty) = if pair p : point 0 of fi r_ fi enddef ; - vardef graph_pair_adjust(expr p)(suffix tx, ty) = (tx xpart p, ty ypart p) enddef ; -% Convert path p from user graph coords to internal graph coords. +% Convert path p from user graph coords to internal graph coords. vardef graph_convert_user_path_to_internal primary p = interim warningcheck :=0 ; graph_scan_path(p, @@ -437,11 +424,11 @@ vardef graph_convert_user_path_to_internal primary p = if Y_.graph_coordinate_type<0 : yscaled -1 fi) enddef ; + % Convert label location t_ from user graph coords to internal graph coords. % The label location should be a pair, or two numbers/strings. If t_ is empty % or a single item of non-pair type, just return t_. Unknown coordinates % produce unknown components in the result. - vardef graph_label_convert_user_to_internal(text t_) = save n_ ; n_=0; interim warningcheck :=0 ; @@ -461,12 +448,13 @@ vardef graph_label_convert_user_to_internal(text t_) = fi enddef ; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Reading data files %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Read a line from file f, extract whitespace-separated tokens ignoring any % initial "%", and return true if at least one token is found. The tokens % are stored in @#1, @#2, .. with "" in the last @#[] entry. - vardef graph_read_line@#(expr f) = save n_, s_ ; string s_; s_ = readfrom f ; @@ -484,9 +472,9 @@ vardef graph_read_line@#(expr f) = fi enddef ; + % Execute c for each line of data read from file f, and stop at the first % line with no data. Commands c can use line number i and tokens $1, $2, ... - def gdata(expr f)(suffix $)(text c) = boolean flag ; for i=1 upto infinity : @@ -498,8 +486,8 @@ def gdata(expr f)(suffix $)(text c) = fi enddef ; -% Read a path from file f. The path is terminated by blank line or EOF. +% Read a path from file f. The path is terminated by blank line or EOF. vardef graph_readpath(expr f) = interim warningcheck :=0 ; save s ; @@ -509,9 +497,9 @@ vardef graph_readpath(expr f) = ) enddef ; + % Append coordinates t to polygonal path @#. The coordinates can be numerics, % strings, or a single pair. - vardef augment@#(text t) = interim warningcheck := 0 ; if not path begingroup @# endgroup : @@ -525,11 +513,12 @@ vardef augment@#(text t) = fi enddef ; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%% Drawing and filling %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Unknown pair components are set to 0 because glabel and gdotlabel understand % unknown coordinates as `0 in absolute units'. - vardef graph_unknown_pair_bbox(expr p) = interim warningcheck:=0 ; if known p : addto graph_current_bb doublepath p ; @@ -546,7 +535,6 @@ enddef ; % Initiate a gdraw or gfill command. This must be done before scanning the % argument, because that could invoke the `if known graph_plot_picture' test in a following % plot option . - def graph_addto = def graph_errorbar_text = enddef ; color graph_foreground ; @@ -554,8 +542,8 @@ def graph_addto = graph_last_drawn := graph_plot_picture := nullpicture ; addto graph_last_drawn enddef; -% Handle the part of a gdraw command that uses path or data file p. +% Handle the part of a Gdraw command that uses path or data file p. def graph_draw expr p = if string p : hide(graph_last_path := graph_readpath(p) ;) graph_convert_user_path_to_internal graph_last_path @@ -568,8 +556,8 @@ def graph_draw expr p = withpen currentpen graph_withlist _op_ enddef ; -% Handle the part of a gdraw command that uses path or data file p. +% Handle the part of a Gdraw command that uses path or data file p. def graph_fill expr p = if string p : hide(graph_last_path := graph_readpath(p) --cycle ;) graph_convert_user_path_to_internal graph_last_path @@ -583,8 +571,8 @@ enddef ; def gdraw = graph_addto doublepath graph_draw enddef ; def gfill = graph_addto contour graph_fill enddef ; -% This is used in graph_draw and graph_fill to allow postprocessing graph_last_drawn +% This is used in graph_draw and graph_fill to allow postprocessing graph_last_drawn def graph_withlist text t_ = t_ ; graph_post_draw; enddef; def witherrorbars(text t) text options = @@ -596,8 +584,6 @@ def witherrorbars(text t) text options = options enddef ; -% new feature: graph_errorbars - picture graph_errorbar_picture ; graph_errorbar_picture := image(draw (left--right) scaled .5 ;) ; %picture graph_xbar_picture ; graph_xbar_picture := image(draw (down--up) scaled .5 ;) ; %picture graph_ybar_picture ; graph_ybar_picture := image(draw (left--right) scaled .5 ;) ; @@ -660,7 +646,6 @@ enddef ; % Set graph_plot_picture so the postprocessing step will plot picture p at each path knot. % Also select nullpen to suppress stroking. - def plot expr p = if known graph_plot_picture : withpen nullpen @@ -672,19 +657,20 @@ def plot expr p = enddef ; % This hides a semicolon that could prematurely end graph_withlist's text argument - def graph_addto_currentpicture primary p = addto currentpicture also p ; enddef; def graph_setbounds = setbounds currentpicture to enddef ; -def gdrawarrow = graph_number_of_arrowheads := 1 ; gdraw enddef; -def gdrawdblarrow = graph_number_of_arrowheads := 2 ; gdraw enddef; + +def gdrawarrow = graph_number_of_arrowheads :=1 ; gdraw enddef; +def gdrawdblarrow = graph_number_of_arrowheads :=2 ; gdraw enddef; + % Post-process the filled or stroked picture graph_last_drawn as follows : (1) update % the bounding box information ; (2) transfer it to graph_current_graph unless the pen has % been set to nullpen to disable stroking ; (3) plot graph_plot_picture at each knot. - vardef graph_post_draw = - save p ; path p ; p = pathpart graph_last_drawn ; + save p ; + path p ; p=pathpart graph_last_drawn; graph_unknown_pair_bbox(p) ; if filled graph_last_drawn or not graph_is_null(penpart graph_last_drawn) : addto graph_current_graph also graph_last_drawn ; @@ -701,23 +687,17 @@ vardef graph_post_draw = if graph_number_of_arrowheads>1 : graph_draw_arrowhead(reverse p, graph_with_pen_and_color(graph_last_drawn)) ; fi - graph_number_of_arrowheads := 0 ; + graph_number_of_arrowheads :=0 ; fi enddef ; - vardef graph_is_null(expr p) = (urcorner p=origin) and (llcorner p=origin) enddef ; + vardef graph_draw_arrowhead(expr p)(text w) = % Draw arrowhead for path p, with list w - %save r ; r := angle(precontrol infinity of p shifted -point infinity of p) ; addto graph_current_graph also - image(fill arrowhead (graph_arrowhead_extent(precontrol infinity of p,point infinity of p)) w ; - draw arrowhead (graph_arrowhead_extent(precontrol infinity of p,point infinity of p)) w - undashed ; -%if (r mod 90 <> 0) : % orientation can be wrong due to remapping -% draw textext("\tfxx " & decimal r) shifted point infinity of p withcolor blue ; -%fi - graph_setbounds point infinity of p..cycle ; - ) ; % rotatedabout(point infinity of p,-r) ; + image(filldraw arrowhead( + graph_arrowhead_extent(precontrol infinity of p, point infinity of p)) w ; + graph_setbounds point infinity of p..cycle) ; enddef ; vardef graph_arrowhead_extent(expr p, q) = @@ -725,6 +705,8 @@ vardef graph_arrowhead_extent(expr p, q) = q enddef ; + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Drawing labels %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Argument c is a drawing command that needs an additional argument p that gives @@ -732,7 +714,6 @@ enddef ; % path. Unknown components of p cause the setbounds path to have width or height 1 instead of 0. % Then graph_unknown_pair_bbox sets these components to 0 and graph_picture_conversion % suppresses subsequent repositioning. - def graph_draw_label(expr p)(suffix $)(text c) = save sdim_ ; pair sdim_; sdim_ := (if unknown xpart p : 1+ fi 0, if unknown ypart p : 1+ fi 0) ; @@ -741,13 +722,14 @@ def graph_draw_label(expr p)(suffix $)(text c) = image(c(p) ; graph_setbounds p--p+sdim_--cycle) _op_ enddef ; + % Stash the result drawing command c in the graph_label table using with list w and % an index based on angle mfun_laboff$. - vardef graph_stash_label(suffix $)(text c) text w = graph_label[1.5+angle mfun_laboff$ /90] = image(c(origin) w) ; enddef ; + def graph_label_location primary p = if pair p : graph_draw_label(p) elseif numeric p : graph_draw_label(point p of pathpart graph_last_drawn) @@ -755,31 +737,33 @@ def graph_label_location primary p = fi enddef ; + % Place label p at user graph coords t using with list w. (t is a time, a pair % or 2 numerics or strings). - vardef glabel@#(expr p)(text t) text w = graph_label_location graph_label_convert_user_to_internal(t) (@#,label@#(p)) w ; enddef; + % Place label p at user graph coords t using with list w and draw a dot there. % (t is a time, a pair, or 2 numerics or strings). - vardef gdotlabel@#(expr p)(text t) text w = graph_label_location graph_label_convert_user_to_internal(t) (@#,dotlabel@#(p)) w ; enddef; + def OUT = enddef ; % location text for outside labels + + %%%%%%%%%%%%%%%%%%%%%%%%%% Grid lines, ticks, etc. %%%%%%%%%%%%%%%%%%%%%%%%%% % Grid lines and tick marks are transformed versions of the templates below. % In the template paths, (0,0) is on the edge of the frame and inward is to % the right. - -path graph_template.tick, graph_template.itick, graph_template.otick, graph_template.grid ; -graph_template.tick = (-3.5bp,0)--(3.5bp,0) ; -graph_template.itick = origin--(7bp,0) ; -graph_template.otick = (-7bp,0)--origin ; -graph_template.grid = origin--(1,0) ; +path Gtemplate.tick, Gtemplate.itick, Gtemplate.otick, Gtemplate.grid ; +Gtemplate.tick = (-3.5bp,0)--(3.5bp,0) ; +Gtemplate.itick = origin--(7bp,0) ; +Gtemplate.otick = (-7bp,0)--origin ; +Gtemplate.grid = origin--(1,0) ; vardef tick@#(expr f,u) text w = graph_tick_label(@#,@,false,f,u,w) ; enddef; @@ -790,82 +774,75 @@ vardef otick@#(expr f,u) text w = graph_tick_label(@#,@,false,f,u,w) ; enddef; vardef grid@#(expr f,u) text w = graph_tick_label(@#,@,true,f,u,w) ; enddef; -% Produce a tick or grid mark for label suffix $, graph_template suffix $$, -% coordinate value u, and with list w. Boolean c tells whether graph_template$$ +% Produce a tick or grid mark for label suffix $, Gtemplate suffix $$, +% coordinate value u, and with list w. Boolean c tells whether Gtemplate$$ % needs scaling by X_.graph_dimensions or Y_.graph_dimensions, % and f gives a format string or a label picture. - def graph_tick_label(suffix $,$$)(expr c, f, u)(text w) = - graph_draw_label(graph_label_convert_user_to_internal(graph_generate_label_position($,u)),, - draw graph_gridline_picture$($$,c,f,u,w) shifted) + graph_draw_label(graph_label_convert_user_to_internal(graph_generate_label_position($,u)),,draw graph_gridline_picture$($$,c,f,u,w) shifted) enddef ; + % Generate label positioning arguments appropriate for label suffix $ and % coordinate u. - def graph_generate_label_position(suffix $)(expr u) = - if pair u : u elseif xpart mfun_laboff.$=0 : u,whatever else : whatever,u fi + if xpart mfun_laboff.$=0 : u,whatever else : whatever,u fi enddef ; + % Generate a picture of a grid line labeled with coordinate value u, picture % or format string f, and with list w. Suffix @# is bot, top, lft, or rt, -% suffix $ identifies entries in the graph_template table, and boolean c tells -% whether to scale graph_template$. - +% suffix $ identifies entries in the Gtemplate table, and boolean c tells +% whether to scale Gtemplate$. vardef graph_gridline_picture@#(suffix $)(expr c, f, u)(text w) = if unknown u : graph_error(u,"Label coordinate should be known") ; nullpicture else : save p ; path p; interim warningcheck :=0 ; graph_autogrid_needed :=false ; - p = graph_template$ zscaled -mfun_laboff@# - if c : graph_xyscale fi - shifted (((.5 + mfun_laboff@# dotprod (.5,.5)) * mfun_laboff@#) graph_xyscale) ; + p = Gtemplate$ zscaled -mfun_laboff@# + if c : Gxyscale fi + shifted (((.5 + mfun_laboff@# dotprod (.5,.5)) * mfun_laboff@#) Gxyscale) ; image(draw p w ; label@#(if string f : format(f,u) else : f fi, point 0 of p)) fi enddef ; +def Gxyscale = xscaled X_.graph_dimensions yscaled Y_.graph_dimensions enddef ; -def graph_xyscale = xscaled X_.graph_dimensions yscaled Y_.graph_dimensions enddef ; % Draw the frame or the part corresponding to label suffix @# using with list w. - vardef frame@# text w = graph_frame_needed :=false ; picture p_ ; p_ = image(draw if str@#<>"" : subpath round(angle mfun_laboff@#*graph_frame_pair_a+graph_frame_pair_b) of fi - unitsquare graph_xyscale w) ; + unitsquare Gxyscale w) ; graph_draw_label((whatever,whatever),,draw p_ shifted) ; enddef ; - -pair graph_frame_pair_a ; graph_frame_pair_a=(1,1)/90; % unitsquare subpath is linear in label angle +pair graph_frame_pair_a ; graph_frame_pair_a=(1,1)/90; % unitsquare subpath is linear in label angle pair graph_frame_pair_b ; graph_frame_pair_b=(.75,2.25); -%%%%%%%%%%%%%%%%%%%%%%%%%% Automatic grid selection %%%%%%%%%%%%%%%%%%%%%%%%%% -string graph_log_marks[] ; % marking options per decade for logarithmic scales -string graph_lin_marks ; % mark spacing options per decade for linear scales -string graph_exp_marks ; % exponent spacing options for logarithmic scales -newinternal graph_minimum_number_of_marks, graph_log_minimum ; -graph_minimum_number_of_marks := 4 ; % minimum number marks generated by auto.x or auto.y -graph_log_minimum := mlog 3 ; % revert to uniform marks when largest/smallest < this -def Gfor(text t) = for i=t endfor enddef ; % to shorten the mark templates below -graph_log_marks[1]="1,2,5" ; -graph_log_marks[2]="1,1.5,2,3,4,5,7" ; -graph_log_marks[3]="1Gfor(6upto10 :,i/5)Gfor(5upto10 :,i/2)Gfor(6upto9 :,i)" ; -graph_log_marks[4]="1Gfor(11upto20 :,i/10)Gfor(11upto25 :,i/5)Gfor(11upto19 :,i/2)" ; -graph_log_marks[5]="1Gfor(21upto40 :,i/20)Gfor(21upto50 :,i/10)Gfor(26upto49 :,i/5)" ; -graph_lin_marks="10,5,2" ; % start with 10 and go down; a final `,1' is appended -graph_exp_marks="20,10,5,2,1" ; +%%%%%%%%%%%%%%%%%%%%%%%%%% Automatic grid selection %%%%%%%%%%%%%%%%%%%%%%%%%% + +string Glmarks[] ; % marking options per decade for logarithmic scales +string Gumarks ; % mark spacing options per decade for linear scales +string Gemarks ; % exponent spacing options for logarithmic scales +newinternal Gmarks, Gminlog ; +Gmarks := 4 ; % minimum number marks generated by auto.x or auto.y +Gminlog := mlog 3 ; % revert to uniform marks when largest/smallest < this + +def Gfor(text t) = for i=t endfor enddef ; % to shorten the mark templates below +Glmarks[1]="1,2,5" ; +Glmarks[2]="1,1.5,2,3,4,5,7" ; +Glmarks[3]="1Gfor(6upto10 :,i/5)Gfor(5upto10 :,i/2)Gfor(6upto9 :,i)" ; +Glmarks[4]="1Gfor(11upto20 :,i/10)Gfor(11upto25 :,i/5)Gfor(11upto19 :,i/2)" ; +Glmarks[5]="1Gfor(21upto40 :,i/20)Gfor(21upto50 :,i/10)Gfor(26upto49 :,i/5)" ; +Gumarks="10,5,2" ; % start with 10 and go down; a final `,1' is appended +Gemarks="20,10,5,2,1" ; -Ten_to0 = 1 ; -Ten_to1 = 10 ; -Ten_to2 = 100 ; -Ten_to3 = 1000 ; -Ten_to4 = 10000 ; % Determine the X_ or Y_ bounds on the range to be covered by automatic grid % marks. Suffix @# is X_ or Y_. The result is log or linear to specify the @@ -874,7 +851,6 @@ Ten_to4 = 10000 ; % are upper and lower bounds in % `modified exponential form'. In modified exponential form, (x,y) means % (x/1000)*10^y, where 1000<=abs x<10000. - vardef graph_bounds@# = interim warningcheck :=0 ; save l, h ; @@ -883,29 +859,28 @@ vardef graph_bounds@# = if abs @#graph_coordinate_type=log : graph_modified_lower := graph_Meform(l)+graph_modified_bias ; graph_modified_higher := graph_Meform(h)+graph_modified_bias ; - if h-l >= graph_log_minimum : log else : linear fi + if h-l >= Gminlog : log else : linear fi else : graph_modified_lower := graph_Feform(l)+graph_modified_bias ; graph_modified_higher := graph_Feform(h)+graph_modified_bias ; linear fi enddef ; - pair graph_modified_bias ; graph_modified_bias=(0,3); pair graph_modified_lower, graph_modified_higher ; -% Scan graph_log_marks[k] and evaluate tokens t for each m where l<=m<=h. +% Scan Glmarks[k] and evaluate tokens t for each m where l<=m<=h. def graph_scan_marks(expr k, l, h)(text t) = - for m=scantokens graph_log_marks[k] : + for m=scantokens Glmarks[k] : exitif m>h ; if m>=l : t fi endfor enddef ; -% Scan graph_log_marks[k] and evaluate tokens t for each m and e where m*10^e belongs -% between l and h (inclusive), where both l and h are in modified exponent form. +% Scan Gmark[k] and evaluate tokens t for each m and e where m*10^e belongs +% between l and h (inclusive), where both l and h are in modified exponent form. def graph_scan_mark(expr k, l, h)(text t) = for e=ypart l upto ypart h : graph_scan_marks(k, if e>ypart l : 1 else : xpart l/1000 fi, @@ -913,29 +888,27 @@ def graph_scan_mark(expr k, l, h)(text t) = endfor enddef ; -% Select a k for which graph_scan_mark(k,...) gives enough marks. +% Select a k for which graph_scan_mark(k,...) gives enough marks. vardef graph_select_mark = save k ; k = 0 ; forever : - exitif unknown graph_log_marks[k+1] ; - exitif 0 graph_scan_mark(incr k, graph_modified_lower, graph_modified_higher, +1) - >= graph_minimum_number_of_marks ; + exitif unknown Glmarks[k+1] ; + exitif 0 graph_scan_mark(incr k, graph_modified_lower, graph_modified_higher, +1) >= Gmarks ; endfor k enddef ; -% Try to select an exponent spacing from graph_exp_marks. If successful, set @# and -% return true +% Try to select an exponent spacing from Gemarks. If successful, set @# and +% return true vardef graph_select_exponent_mark@# = numeric @# ; - for e=scantokens graph_exp_marks : + for e=scantokens Gemarks : @# = e ; exitif floor(ypart graph_modified_higher/e) - - floor(graph_modified_exponent_ypart(graph_modified_lower)/e) - >= graph_minimum_number_of_marks ; + floor(graph_modified_exponent_ypart(graph_modified_lower)/e) >= Gmarks ; numeric @# ; endfor known @# @@ -943,17 +916,17 @@ enddef ; vardef graph_modified_exponent_ypart(expr p) = ypart p if xpart p=1000 : -1 fi enddef ; -% Compute the mark spacing d between xpart graph_modified_lower and xpart graph_modified_higher. +% Compute the mark spacing d between xpart graph_modified_lower and xpart graph_modified_higher. vardef graph_tick_mark_spacing = interim warningcheck :=0 ; save m, n, d ; - m = graph_minimum_number_of_marks ; + m = Gmarks ; n = 1 for i=1 upto (mlog(xpart graph_modified_higher-xpart graph_modified_lower) - mlog m)/mlogten : *10 endfor ; if n<=1000 : - for x=scantokens graph_lin_marks : + for x=scantokens Gumarks : d = n*x ; exitif 0 graph_generate_numbers(d,+1)>=m ; numeric d ; @@ -962,24 +935,25 @@ vardef graph_tick_mark_spacing = if known d : d else : n fi enddef ; + def graph_generate_numbers(expr d)(text t) = for m = d*ceiling(xpart graph_modified_lower/d) step d until xpart graph_modified_higher : t endfor enddef ; + % Evaluate tokens t for exponents e in multiples of d in the range determined % by graph_modified_lower and graph_modified_higher. - def graph_generate_exponents(expr d)(text t) = for e = d*floor(graph_modified_exponent_ypart(graph_modified_lower)/d+1) step d until d*floor(ypart graph_modified_higher/d) : t endfor enddef ; + % Adjust graph_modified_lower and graph_modified_higher so their exponent parts match % and they are in true exponent form ((x,y) means x*10^y). Return the new exponent. - vardef graph_match_exponents = interim warningcheck := 0 ; save e ; @@ -992,10 +966,10 @@ vardef graph_match_exponents = e enddef ; + % Assume e is an integer and either m=0 or 1<=abs(m)<10000. Find m*(10^e) % and represent the result as a string if its absolute value would be at least % 4096 or less than .1. It is OK to return 0 as a string or a numeric. - vardef graph_factor_and_exponent_to_string(expr m, e) = if (e>3)or(e<-4) : decimal m & "e" & decimal e @@ -1010,6 +984,7 @@ vardef graph_factor_and_exponent_to_string(expr m, e) = fi enddef ; + def auto suffix $ = hide(def graph_comma= hide(def graph_comma=,enddef) enddef) if graph_bounds.graph_suffix($)=log : @@ -1027,6 +1002,7 @@ def auto suffix $ = fi enddef ; + string Autoform ; Autoform = "%g"; %vardef autogrid(suffix tx, ty) text w = @@ -1077,11 +1053,12 @@ vardef autogrid(suffix tx, ty) text w = fi enddef ; + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% endgraph %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def endgraph = if graph_autogrid_needed : autogrid(otick.bot, otick.lft) ; fi - if graph_frame_needed : frame ; fi + if graph_frame_needed : frame ; fi setcoords(linear,linear) ; interim truecorners :=1 ; for b=bbox graph_finished_graph : @@ -1098,9 +1075,14 @@ enddef ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% We format in luatex (using \mathematics{}) ... % we could pass via variables and save escaping as that is inefficient +Ten_to0 = 1 ; +Ten_to1 = 10 ; +Ten_to2 = 100 ; +Ten_to3 = 1000 ; +Ten_to4 = 10000 ; + if unknown context_mlib : vardef escaped_format(expr s) = @@ -1126,8 +1108,6 @@ if unknown context_mlib : fi ; -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % A couple of extensions : % Define a function plotsymbol() returning a picture : 10 different shapes, diff --git a/metapost/context/base/mp-tool.mpii b/metapost/context/base/mp-tool.mpii index 62bd122f5..f363f655e 100644 --- a/metapost/context/base/mp-tool.mpii +++ b/metapost/context/base/mp-tool.mpii @@ -5,13 +5,17 @@ %D subtitle=auxiliary macros, %D author=Hans Hagen, %D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] +%D copyright={PRAGMA / Hans Hagen \& Ton Otten}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% def loadfile(expr name) = scantokens("input " & name & ";") enddef ; +% a cleanup is needed, like using image and alike +% use a few more "newinternal"'s + +%D This module is rather preliminary and subjected to +%D changes. if known context_tool : endinput ; fi ; @@ -28,8 +32,6 @@ let @## = @# ; if not known mpversion : string mpversion ; mpversion := "0.641" ; fi ; -newinternal metapostversion ; metapostversion := scantokens(mpversion) ; - % vardef mpversiongt(expr s) = % scantokens (mpversion & " > " & if numeric s : decimal s else : s fi) % enddef ; @@ -83,14 +85,20 @@ mpprocset := 1 ; % % protect ; -string space ; space := char 32 ; -string CRLF ; CRLF := char 10 & char 13 ; +%D By including this module, \METAPOST\ automatically writes a +%D high resolution boundingbox to the \POSTSCRIPT\ file. This +%D hack is due to John Hobby himself. + +% When somehow the first one gets no HiRes, then make sure +% that the format matches the mem sizes in the config file. + +string space ; space = char 32 ; vardef ddecimal primary p = - decimal xpart p & " " & decimal ypart p + decimal xpart p & " " & decimal ypart p enddef ; -%D Plain compatibility: +%D Plain compatibility string plain_compatibility_data ; plain_compatibility_data := "" ; @@ -104,7 +112,7 @@ def stopplaincompatibility = enddef ; % is now built in -% + % extra_endfig := extra_endfig % & "special " % & "(" @@ -116,11 +124,6 @@ enddef ; % & "&ddecimal urcorner currentpicture" % & ");"; -%D More neutral: - -let triplet = rgbcolor ; -let quadruplet = cmykcolor ; - %D Crap (experimental, not used): def forcemultipass = @@ -129,28 +132,12 @@ enddef ; %D Colors: -newinternal nocolormodel ; nocolormodel := 1 ; -newinternal greycolormodel ; greycolormodel := 3 ; -newinternal graycolormodel ; graycolormodel := 3 ; -newinternal rgbcolormodel ; rgbcolormodel := 5 ; -newinternal cmykcolormodel ; cmykcolormodel := 7 ; +nocolormodel := 1 ; +greycolormodel := 3 ; +rgbcolormodel := 5 ; +cmykcolormodel := 7 ; let grayscale = numeric ; -let greyscale = numeric ; - -vardef colorpart expr c = - if not picture c : - 0 - elseif colormodel c = greycolormodel : - greypart c - elseif colormodel c = rgbcolormodel : - (redpart c,greenpart c,bluepart c) - elseif colormodel c = cmykcolormodel : - (cyanpart c,magentapart c,yellowpart c,blackpart c) - else : - 0 % black - fi -enddef ; vardef colorlike(text c) text v = % colorlike(a) b, c, d ; save _p_ ; picture _p_ ; @@ -161,19 +148,25 @@ vardef colorlike(text c) text v = % colorlike(a) b, c, d ; elseif (colormodel _p_ = rgbcolormodel) : rgbcolor i ; else : - greycolor i ; + grayscale i ; fi ; endfor ; enddef ; +% if (unknown colormodel) : +% def colormodel = +% rgbcolormodel +% enddef ; +% fi ; + %D Also handy (when we flush colors): vardef dddecimal primary c = - decimal redpart c & " " & decimal greenpart c & " " & decimal bluepart c + decimal redpart c & " " & decimal greenpart c & " " & decimal bluepart c enddef ; vardef ddddecimal primary c = - decimal cyanpart c & " " & decimal magentapart c & " " & decimal yellowpart c & " " & decimal blackpart c + decimal cyanpart c & " " & decimal magentapart c & " " & decimal yellowpart c & " " & decimal blackpart c enddef ; vardef colordecimals primary c = @@ -200,34 +193,39 @@ enddef ; %D we need some trickery when we have multiple files. if unknown collapse_data : - boolean collapse_data ; - collapse_data := false ; + boolean collapse_data ; collapse_data := false ; fi ; boolean savingdata ; savingdata := false ; boolean savingdatadone ; savingdatadone := false ; def savedata expr txt = - write if collapse_data : - txt - else : - if savingdata : txt else : "\MPdata{" & decimal charcode & "}{" & txt & "}" fi & "%" - fi to data_mpd_file ; + if collapse_data : + write txt to data_mpd_file ; + else : + write if savingdata : txt else : + "\MPdata{" & decimal charcode & "}{" & txt & "}" + fi + & "%" to data_mpd_file ; + fi ; enddef ; def startsavingdata = - savingdata := true ; - savingdatadone := true ; - if collapse_data : - write "\MPdata{" & decimal charcode & "}{%" to data_mpd_file ; - fi ; + savingdata := true ; + savingdatadone := true ; + if collapse_data : + write + "\MPdata{" & decimal charcode & "}{%" + to + data_mpd_file ; + fi ; enddef ; def stopsavingdata = - if collapse_data : - write "}%" to data_mpd_file ; - fi ; - savingdata := false ; + if collapse_data : + write "}%" to data_mpd_file ; + fi ; + savingdata := false ; enddef ; def finishsavingdata = @@ -255,130 +253,119 @@ def newpair text v = forsuffixes i=v : save i ; pair i ; endfor ; endd %D box, draw the graphics that may not count, and restore the %D bounding box. %D -%D \starttyping +%D \starttypen %D push_boundingbox currentpicture; %D pop_boundingbox currentpicture; -%D \stoptyping +%D \stoptypen %D %D The bounding box can be called with: %D -%D \starttyping +%D \starttypen %D boundingbox currentpicture %D inner_boundingbox currentpicture %D outer_boundingbox currentpicture -%D \stoptyping +%D \stoptypen %D %D Especially the latter one can be of use when we include %D the graphic in a document that is clipped to the bounding %D box. In such occasions one can use: %D -%D \starttyping +%D \starttypen %D set_outer_boundingbox currentpicture; -%D \stoptyping +%D \stoptypen %D %D Its counterpart is: %D -%D \starttyping +%D \starttypen %D set_inner_boundingbox p -%D \stoptyping - -path mfun_boundingbox_stack ; -numeric mfun_boundingbox_stack_depth ; - -mfun_boundingbox_stack_depth := 0 ; +%D \stoptypen -def pushboundingbox text p = - mfun_boundingbox_stack_depth := mfun_boundingbox_stack_depth + 1 ; - mfun_boundingbox_stack[mfun_boundingbox_stack_depth] := boundingbox p ; -enddef ; +path pushed_boundingbox; -def popboundingbox text p = - setbounds p to mfun_boundingbox_stack[mfun_boundingbox_stack_depth] ; - mfun_boundingbox_stack[mfun_boundingbox_stack_depth] := origin ; - mfun_boundingbox_stack_depth := mfun_boundingbox_stack_depth - 1 ; -enddef ; +def push_boundingbox text p = + pushed_boundingbox := boundingbox p; +enddef; -let push_boundingbox = pushboundingbox ; % downward compatible -let pop_boundingbox = popboundingbox ; % downward compatible +def pop_boundingbox text p = + setbounds p to pushed_boundingbox; +enddef; vardef boundingbox primary p = - if (path p) or (picture p) : - llcorner p -- lrcorner p -- urcorner p -- ulcorner p - else : - origin - fi -- cycle + if (path p) or (picture p) : + llcorner p -- lrcorner p -- urcorner p -- ulcorner p + else : + origin + fi -- cycle enddef; -vardef innerboundingbox primary p = - top rt llcorner p -- - top lft lrcorner p -- - bot lft urcorner p -- - bot rt ulcorner p -- cycle +vardef inner_boundingbox primary p = + top rt llcorner p -- + top lft lrcorner p -- + bot lft urcorner p -- + bot rt ulcorner p -- cycle enddef; -vardef outerboundingbox primary p = - bot lft llcorner p -- - bot rt lrcorner p -- - top rt urcorner p -- - top lft ulcorner p -- cycle +vardef outer_boundingbox primary p = + bot lft llcorner p -- + bot rt lrcorner p -- + top rt urcorner p -- + top lft ulcorner p -- cycle enddef; -def inner_boundingbox = innerboundingbox enddef ; -def outer_boundingbox = outerboundingbox enddef ; +def innerboundingbox = inner_boundingbox enddef ; +def outerboundingbox = outer_boundingbox enddef ; -vardef set_inner_boundingbox text q = % obsolete - setbounds q to innerboundingbox q; +vardef set_inner_boundingbox text q = + setbounds q to inner_boundingbox q; enddef; -vardef set_outer_boundingbox text q = % obsolete - setbounds q to outerboundingbox q; +vardef set_outer_boundingbox text q = + setbounds q to outer_boundingbox q; enddef; -%D Some missing functions can be implemented rather straightforward (thanks to -%D Taco and others): +%D Some missing functions can be implemented rather +%D straightforward: + +numeric Pi ; Pi := 3.1415926 ; -pi := 3.14159265358979323846 ; radian := 180/pi ; % 2pi*radian = 360 ; +vardef sqr primary x = (x*x) enddef ; +vardef log primary x = (if x=0: 0 else: mlog(x)/mlog(10) fi) enddef ; +vardef ln primary x = (if x=0: 0 else: mlog(x)/256 fi) enddef ; +vardef exp primary x = ((mexp 256)**x) enddef ; +vardef inv primary x = (if x=0: 0 else: x**-1 fi) enddef ; -% let +++ = ++ ; +vardef pow (expr x,p) = (x**p) enddef ; -numeric Pi ; Pi := pi ; % for some old compatibility reasons i guess +vardef asin primary x = (x+(x**3)/6+3(x**5)/40) enddef ; +vardef acos primary x = (asin(-x)) enddef ; +vardef atan primary x = (x-(x**3)/3+(x**5)/5-(x**7)/7) enddef ; +vardef tand primary x = (sind(x)/cosd(x)) enddef ; -vardef sqr primary x = x*x enddef ; -vardef log primary x = if x=0: 0 else: mlog(x)/mlog(10) fi enddef ; -vardef ln primary x = if x=0: 0 else: mlog(x)/256 fi enddef ; -vardef exp primary x = (mexp 256)**x enddef ; -vardef inv primary x = if x=0: 0 else: x**-1 fi enddef ; +%D Here are Taco Hoekwater's alternatives (but +%D vardef'd and primaried). -vardef pow (expr x,p) = x**p enddef ; +pi := 3.1415926 ; radian := 180/pi ; % 2pi*radian = 360 ; -vardef tand primary x = sind(x)/cosd(x) enddef ; -vardef cotd primary x = cosd(x)/sind(x) enddef ; +vardef tand primary x = (sind(x)/cosd(x)) enddef ; +vardef cotd primary x = (cosd(x)/sind(x)) enddef ; -vardef sin primary x = sind(x*radian) enddef ; -vardef cos primary x = cosd(x*radian) enddef ; -vardef tan primary x = sin(x)/cos(x) enddef ; -vardef cot primary x = cos(x)/sin(x) enddef ; +vardef sin primary x = (sind(x*radian)) enddef ; +vardef cos primary x = (cosd(x*radian)) enddef ; +vardef tan primary x = (sin(x)/cos(x)) enddef ; +vardef cot primary x = (cos(x)/sin(x)) enddef ; -vardef asin primary x = angle((1+-+x,x)) enddef ; -vardef acos primary x = angle((x,1+-+x)) enddef ; -vardef atan primary x = angle(1,x) enddef ; +vardef asin primary x = angle((1+-+x,x)) enddef ; +vardef acos primary x = angle((x,1+-+x)) enddef ; -vardef invsin primary x = (asin(x))/radian enddef ; -vardef invcos primary x = (acos(x))/radian enddef ; -vardef invtan primary x = (atan(x))/radian enddef ; +vardef invsin primary x = ((asin(x))/radian) enddef ; +vardef invcos primary x = ((acos(x))/radian) enddef ; -vardef acosh primary x = ln(x+(x+-+1)) enddef ; -vardef asinh primary x = ln(x+(x++1)) enddef ; +vardef acosh primary x = ln(x+(x+-+1)) enddef ; +vardef asinh primary x = ln(x+(x++1)) enddef ; vardef sinh primary x = save xx ; xx = exp x ; (xx-1/xx)/2 enddef ; vardef cosh primary x = save xx ; xx = exp x ; (xx+1/xx)/2 enddef ; -%D Sometimes this is handy: - -def undashed = - dashed nullpicture -enddef ; - %D We provide two macros for drawing stripes across a shape. %D The first method (with the n suffix) uses another method, %D slower in calculation, but more efficient when drawn. The @@ -387,218 +374,101 @@ enddef ; %D the second argument identifier the way the shape is to be %D drawn. %D -%D \starttyping +%D \starttypen %D stripe_path_n %D (dashed evenly withcolor blue) %D (filldraw) %D fullcircle xscaled 100 yscaled 40 shifted (50,50) withpen pencircle scaled 4; -%D \stoptyping +%D \stoptypen %D %D The a (or angle) alternative supports arbitrary angles and %D is therefore more versatile. %D -%D \starttyping +%D \starttypen %D stripe_path_a %D (withpen pencircle scaled 2 withcolor red) %D (draw) %D fullcircle xscaled 100 yscaled 40 withcolor blue; -%D \stoptyping -%D -%D We have two alternatives, controlled by arguments or defaults (when arguments -%D are zero). -%D -%D The newer and nicer interface is used as follows (triggered by a question by Mari): -%D -%D \starttyping -%D draw image (draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green) numberstriped (1,10,3) withcolor red ; -%D draw image (draw fullcircle scaled 3cm shifted (3cm,0cm) withcolor green) numberstriped (2,20,3) withcolor green ; -%D draw image (draw fullcircle scaled 3cm shifted (3cm,3cm) withcolor green) numberstriped (3,10,5) withcolor blue ; -%D draw image (draw fullcircle scaled 3cm shifted (0cm,3cm) withcolor green) numberstriped (4,20,5) withcolor yellow ; -%D -%D draw image (draw fullcircle scaled 3cm shifted (6cm,0cm) withcolor green) anglestriped (1,20,2) withcolor red ; -%D draw image (draw fullcircle scaled 3cm shifted (9cm,0cm) withcolor green) anglestriped (2,40,2) withcolor green ; -%D draw image (draw fullcircle scaled 3cm shifted (9cm,3cm) withcolor green) anglestriped (3,60,2) withcolor blue ; -%D draw image (draw fullcircle scaled 3cm shifted (6cm,3cm) withcolor green) anglestriped (4,80,2) withcolor yellow ; -%D -%D draw image ( -%D draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ; -%D draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue withpen pencircle scaled 3mm ; -%D ) shifted (9cm,0cm) numberstriped (1,10,3) withcolor red ; -%D -%D draw image ( -%D draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ; -%D draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue withpen pencircle scaled 3mm ; -%D ) shifted (12cm,0cm) numberstriped (2,10,3) withcolor red ; -%D -%D draw image ( -%D draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ; -%D draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue withpen pencircle scaled 3mm ; -%D ) shifted (9cm,5cm) numberstriped (3,10,3) withcolor red ; +%D \stoptypen %D -%D draw image ( -%D draw fullcircle scaled 3cm shifted (0cm,0cm) withcolor green withpen pencircle scaled 2mm ; -%D draw fullcircle scaled 2cm shifted (0cm,1cm) withcolor blue withpen pencircle scaled 3mm ; -%D ) shifted (12cm,5cm) numberstriped (4,10,3) withcolor red ; -%D \stoptyping +%D The first alternative obeys: stripe_n := 10; stripe_slot := 3; -stripe_gap := 5; -stripe_angle := 45; -def mfun_tool_striped_number_action text extra = - for i = 1/used_n step 1/used_n until 1 : - draw point (1+i) of bounds -- point (3-i) of bounds withpen pencircle scaled penwidth extra ; - endfor ; - for i = 0 step 1/used_n until 1 : - draw point (3+i) of bounds -- point (1-i) of bounds withpen pencircle scaled penwidth extra ; - endfor ; -enddef ; - -def mfun_tool_striped_set_options(expr option) = - save isinner, swapped ; - boolean isinner, swapped ; - if option = 1 : - isinner := false ; - swapped := false ; - elseif option = 2 : - isinner := true ; - swapped := false ; - elseif option = 3 : - isinner := false ; - swapped := true ; - elseif option = 4 : - isinner := true ; - swapped := true ; - else : - isinner := false ; - swapped := false ; - fi ; -enddef ; - -vardef mfun_tool_striped_number(expr option, p, s_n, s_slot) text extra = - image ( - begingroup ; - save pattern, shape, bounds, penwidth, used_n, used_slot ; - picture pattern, shape ; path bounds ; numeric used_s, used_slot ; - mfun_tool_striped_set_options(option) ; - used_slot := if s_slot = 0 : stripe_slot else : s_slot fi ; - used_n := if s_n = 0 : stripe_n else : s_n fi ; - shape := image(draw p) ; - bounds := boundingbox shape ; - penwidth := min(ypart urcorner shape - ypart llcorner shape, xpart urcorner shape - xpart llcorner shape) / (used_slot * used_n) ; - pattern := image ( - if isinner : - mfun_tool_striped_number_action extra ; - for s within shape : - if stroked s or filled s : - clip currentpicture to pathpart s ; - fi - endfor ; - else : - for s within shape : - if stroked s or filled s : - draw image ( - mfun_tool_striped_number_action extra ; - clip currentpicture to pathpart s ; - ) ; - fi ; - endfor ; - fi ; - ) ; - if swapped : - addto currentpicture also shape ; - addto currentpicture also pattern ; - else : - addto currentpicture also pattern ; - addto currentpicture also shape ; - fi ; - endgroup ; - ) -enddef ; - -def mfun_tool_striped_angle_action text extra = - for i = minimum -.5used_gap step used_gap until maximum : - draw (minimum,i) -- (maximum,i) extra ; - endfor ; - currentpicture := currentpicture rotated used_angle ; -enddef ; - -vardef mfun_tool_striped_angle(expr option, p, s_angle, s_gap) text extra = - image ( - begingroup ; - save pattern, shape, mask, maximum, minimum, centrum, used_angle, used_gap ; - picture pattern, shape, mask ; numeric maximum, minimum ; pair centrum ; numeric used_angle, used_gap ; - mfun_tool_striped_set_options(option) ; - used_angle := if s_angle = 0 : stripe_angle else : s_angle fi ; - used_gap := if s_gap = 0 : stripe_gap else : s_gap fi ; - shape := image(draw p) ; - centrum := center shape ; - shape := shape shifted - centrum ; - mask := shape rotated used_angle ; - maximum := max (xpart llcorner mask, xpart urcorner mask, ypart llcorner mask, ypart urcorner mask) ; - minimum := min (xpart llcorner mask, xpart urcorner mask, ypart llcorner mask, ypart urcorner mask) ; - pattern := image ( - if isinner : - mfun_tool_striped_angle_action extra ; - for s within shape : - if stroked s or filled s : - clip currentpicture to pathpart s ; - fi - endfor ; - else : - for s within shape : - if stroked s or filled s : - draw image ( - mfun_tool_striped_angle_action extra ; - clip currentpicture to pathpart s ; - ) ; - fi ; - endfor ; - fi ; - ) ; - if swapped : - addto currentpicture also shape ; - addto currentpicture also pattern ; - else : - addto currentpicture also pattern ; - addto currentpicture also shape ; - fi ; - currentpicture := currentpicture shifted - centrum ; - endgroup ; - ) -enddef; - -newinternal striped_normal_inner ; striped_normal_inner := 1 ; -newinternal striped_reverse_inner ; striped_reverse_inner := 2 ; -newinternal striped_normal_outer ; striped_normal_outer := 3 ; -newinternal striped_reverse_outer ; striped_reverse_outer := 4 ; - -secondarydef p anglestriped s = - mfun_tool_striped_angle(redpart s,p,greenpart s,bluepart s) -enddef ; - -secondarydef p numberstriped s = - mfun_tool_striped_number(redpart s,p,greenpart s,bluepart s) -enddef ; +%D When no pen dimensions are passed, the slot determines +%D the spacing. +%D +%D The angle alternative is influenced by: -% for old times sake: +stripe_gap := 5; +stripe_angle := 45; def stripe_path_n (text s_spec) (text s_draw) expr s_path = - do_stripe_path_n (s_spec) (s_draw) (s_path) + do_stripe_path_n (s_spec) (s_draw) (s_path) enddef; def do_stripe_path_n (text s_spec) (text s_draw) (expr s_path) text s_text = - draw image(s_draw s_path s_text) numberstriped(3,0,0) s_spec ; -enddef ; + begingroup + save curpic, newpic, bb, pp, ww; + picture curpic, newpic; + path bb, pp; + pp := s_path; + curpic := currentpicture; + currentpicture := nullpicture; + s_draw pp s_text; + bb := boundingbox currentpicture; + newpic := currentpicture; + currentpicture := nullpicture; + ww := min(ypart urcorner newpic - ypart llcorner newpic, + xpart urcorner newpic - xpart llcorner newpic); + ww := ww/(stripe_slot*stripe_n); + for i=1/stripe_n step 1/stripe_n until 1: + draw point (1+i) of bb -- point (3-i) of bb + withpen pencircle scaled ww s_spec ; + endfor; + for i=0 step 1/stripe_n until 1: + draw point (3+i) of bb -- point (1-i) of bb + withpen pencircle scaled ww s_spec; + endfor; + clip currentpicture to pp; + addto newpic also currentpicture; + currentpicture := curpic; + addto currentpicture also newpic; + endgroup +enddef; def stripe_path_a (text s_spec) (text s_draw) expr s_path = - do_stripe_path_a (s_spec) (s_draw) (s_path) + do_stripe_path_a (s_spec) (s_draw) (s_path) enddef; def do_stripe_path_a (text s_spec) (text s_draw) (expr s_path) text s_text = - draw image(s_draw s_path s_text) anglestriped(3,0,0) s_spec ; -enddef ; + begingroup + save curpic, newpic, pp; picture curpic, newpic; path pp ; + pp := s_path ; + curpic := currentpicture; + currentpicture := nullpicture; + s_draw pp s_text ; + def do_stripe_rotation (expr p) = + (currentpicture rotatedaround(center p,stripe_angle)) + enddef ; + s_max := max + (xpart llcorner do_stripe_rotation(currentpicture), + xpart urcorner do_stripe_rotation(currentpicture), + ypart llcorner do_stripe_rotation(currentpicture), + ypart urcorner do_stripe_rotation(currentpicture)); + newpic := currentpicture; + currentpicture := nullpicture; + for i=-s_max-.5stripe_gap step stripe_gap until s_max: + draw (-s_max,i)--(s_max,i) s_spec; + endfor; + currentpicture := do_stripe_rotation(newpic); + clip currentpicture to pp ; + addto newpic also currentpicture; + currentpicture := curpic; + addto currentpicture also newpic; + endgroup +enddef; %D A few normalizing macros: %D @@ -637,43 +507,46 @@ enddef ; % natural_width := xpart urcorner currentpicture - xpart llcorner currentpicture; % currentpicture := currentpicture scaled (the_width/natural_width) ; +% TODO TODO TODO TODO, not yet ok + primarydef p xsized w = - (p if (bbwidth (p)>0) and (w>0) : scaled (w/bbwidth (p)) fi) + (p if (bbwidth (p)>0) and (w>0) : scaled (w/bbwidth (p)) fi) enddef ; primarydef p ysized h = - (p if (bbheight(p)>0) and (h>0) : scaled (h/bbheight(p)) fi) + (p if (bbheight(p)>0) and (h>0) : scaled (h/bbheight(p)) fi) enddef ; primarydef p xysized s = - begingroup + begingroup ; save wh, w, h ; pair wh ; numeric w, h ; wh := paired (s) ; w := bbwidth(p) ; h := bbheight(p) ; - p - if (w>0) and (h>0) : - if xpart wh > 0 : xscaled (xpart wh/w) fi - if ypart wh > 0 : yscaled (ypart wh/h) fi - fi - endgroup + (p if (w>0) and (h>0) : + if xpart wh > 0 : xscaled (xpart wh/w) fi + if ypart wh > 0 : yscaled (ypart wh/h) fi + fi) + endgroup enddef ; -let sized = xysized ; +primarydef p sized wh = + (p xysized wh) +enddef ; -def xscale_currentpicture(expr w) = % obsolete - currentpicture := currentpicture xsized w ; +def xscale_currentpicture(expr w) = + currentpicture := currentpicture xsized w ; enddef; -def yscale_currentpicture(expr h) = % obsolete - currentpicture := currentpicture ysized h ; +def yscale_currentpicture(expr h) = + currentpicture := currentpicture ysized h ; enddef; -def xyscale_currentpicture(expr w, h) = % obsolete - currentpicture := currentpicture xysized (w,h) ; +def xyscale_currentpicture(expr w, h) = + currentpicture := currentpicture xysized (w,h) ; enddef; -def scale_currentpicture(expr w, h) = % obsolete - currentpicture := currentpicture xsized w ; - currentpicture := currentpicture ysized h ; +def scale_currentpicture(expr w, h) = + currentpicture := currentpicture xsized w ; + currentpicture := currentpicture ysized h ; enddef; %D A full circle is centered at the origin, while a unitsquare @@ -689,28 +562,28 @@ unitcircle := fullcircle shifted urcorner fullcircle ; path urcircle, ulcircle, llcircle, lrcircle ; -urcircle := origin -- (+.5,0) & (+.5,0){up} .. (0,+.5) & (0,+.5) -- cycle ; -ulcircle := origin -- (0,+.5) & (0,+.5){left} .. (-.5,0) & (-.5,0) -- cycle ; -llcircle := origin -- (-.5,0) & (-.5,0){down} .. (0,-.5) & (0,-.5) -- cycle ; -lrcircle := origin -- (0,-.5) & (0,-.5){right} .. (+.5,0) & (+.5,0) -- cycle ; +urcircle := origin--(+.5,0)&(+.5,0){up} ..(0,+.5)&(0,+.5)--cycle ; +ulcircle := origin--(0,+.5)&(0,+.5){left} ..(-.5,0)&(-.5,0)--cycle ; +llcircle := origin--(-.5,0)&(-.5,0){down} ..(0,-.5)&(0,-.5)--cycle ; +lrcircle := origin--(0,-.5)&(0,-.5){right}..(+.5,0)&(+.5,0)--cycle ; path tcircle, bcircle, lcircle, rcircle ; -tcircle = origin -- (+.5,0) & (+.5,0) {up} .. (0,+.5) .. {down} (-.5,0) -- cycle ; -bcircle = origin -- (-.5,0) & (-.5,0) {down} .. (0,-.5) .. {up} (+.5,0) -- cycle ; -lcircle = origin -- (0,+.5) & (0,+.5) {left} .. (-.5,0) .. {right} (0,-.5) -- cycle ; -rcircle = origin -- (0,-.5) & (0,-.5) {right} .. (+.5,0) .. {left} (0,+.5) -- cycle ; +tcircle = origin--(+.5,0)&(+.5,0){up} ..(0,+.5)..{down} (-.5,0)--cycle ; +bcircle = origin--(-.5,0)&(-.5,0){down} ..(0,-.5)..{up} (+.5,0)--cycle ; +lcircle = origin--(0,+.5)&(0,+.5){left} ..(-.5,0)..{right}(0,-.5)--cycle ; +rcircle = origin--(0,-.5)&(0,-.5){right}..(+.5,0)..{left} (0,+.5)--cycle ; -path urtriangle, ultriangle, lltriangle, lrtriangle ; % watch out: it's contrary to what you expect and starts in the origin +path urtriangle, ultriangle, lltriangle, lrtriangle ; -urtriangle := origin -- (+.5,0) -- (0,+.5) -- cycle ; -ultriangle := origin -- (0,+.5) -- (-.5,0) -- cycle ; -lltriangle := origin -- (-.5,0) -- (0,-.5) -- cycle ; -lrtriangle := origin -- (0,-.5) -- (+.5,0) -- cycle ; +urtriangle := origin--(+.5,0)--(0,+.5)--cycle ; +ultriangle := origin--(0,+.5)--(-.5,0)--cycle ; +lltriangle := origin--(-.5,0)--(0,-.5)--cycle ; +lrtriangle := origin--(0,-.5)--(+.5,0)--cycle ; path unitdiamond, fulldiamond ; -unitdiamond := (.5,0) -- (1,.5) -- (.5,1) -- (0,.5) -- cycle ; +unitdiamond := (.5,0)--(1,.5)--(.5,1)--(0,.5)--cycle ; fulldiamond := unitdiamond shifted - center unitdiamond ; %D More robust: @@ -725,49 +598,46 @@ fulldiamond := unitdiamond shifted - center unitdiamond ; %D Shorter -primarydef p xyscaled q = % secundarydef does not work out well - begingroup - save qq ; pair qq ; - qq = paired(q) ; - p - if xpart qq <> 0 : xscaled (xpart qq) fi - if ypart qq <> 0 : yscaled (ypart qq) fi - endgroup +primarydef p xyscaled q = + begingroup ; save qq ; pair qq ; qq = paired(q) ; + ( p + if xpart qq<>0 : xscaled (xpart qq) fi + if ypart qq<>0 : yscaled (ypart qq) fi ) + endgroup enddef ; -%D Some personal code that might move to another module +%D Experimenteel, zie folder-3.tex. def set_grid(expr w, h, nx, ny) = - boolean grid[][] ; boolean grid_full ; - numeric grid_w, grid_h, grid_nx, grid_ny, grid_x, grid_y, grid_left ; - grid_w := w ; - grid_h := h ; - grid_nx := nx ; - grid_ny := ny ; - grid_x := round(w/grid_nx) ; % +.5) ; - grid_y := round(h/grid_ny) ; % +.5) ; - grid_left := (1+grid_x)*(1+grid_y) ; - grid_full := false ; - for i=0 upto grid_x : - for j=0 upto grid_y : - grid[i][j] := false ; - endfor ; + boolean grid[][] ; boolean grid_full ; + grid_w := w ; + grid_h := h ; + grid_nx := nx ; + grid_ny := ny ; + grid_x := round(w/grid_nx) ; % +.5) ; + grid_y := round(h/grid_ny) ; % +.5) ; + grid_left := (1+grid_x)*(1+grid_y) ; + grid_full := false ; + for i=0 upto grid_x: + for j=0 upto grid_y: + grid[i][j] := false ; endfor ; + endfor ; enddef ; vardef new_on_grid(expr _dx_, _dy_) = - dx := _dx_ ; - dy := _dy_ ; - ddx := min(round(dx/grid_nx),grid_x) ; % +.5),grid_x) ; - ddy := min(round(dy/grid_ny),grid_y) ; % +.5),grid_y) ; - if not grid_full and not grid[ddx][ddy] : - grid[ddx][ddy] := true ; - grid_left := grid_left-1 ; - grid_full := (grid_left=0) ; - true - else : - false - fi + dx := _dx_ ; + dy := _dy_ ; + ddx := min(round(dx/grid_nx),grid_x) ; % +.5),grid_x) ; + ddy := min(round(dy/grid_ny),grid_y) ; % +.5),grid_y) ; + if not grid_full and not grid[ddx][ddy]: + grid[ddx][ddy] := true ; + grid_left := grid_left-1 ; + grid_full := (grid_left=0) ; + true + else: + false + fi enddef ; %D usage: \type{innerpath peepholed outerpath}. @@ -780,71 +650,79 @@ enddef ; %D endfig; secondarydef p peepholed q = - begingroup - save start ; pair start ; - start := point 0 of p ; - if xpart start >= xpart center p : - if ypart start >= ypart center p : - urcorner q -- ulcorner q -- llcorner q -- lrcorner q -- - reverse p -- lrcorner q -- cycle - else : - lrcorner q -- urcorner q -- ulcorner q -- llcorner q -- - reverse p -- llcorner q -- cycle - fi + begingroup ; + save start ; pair start ; start := point 0 of p ; + if xpart start >= xpart center p : + if ypart start >= ypart center p : + urcorner q -- ulcorner q -- llcorner q -- lrcorner q -- + reverse p -- lrcorner q -- cycle else : - if ypart start > ypart center p : - ulcorner q -- llcorner q -- lrcorner q -- urcorner q -- - reverse p -- urcorner q -- cycle - else : - llcorner q -- lrcorner q -- urcorner q -- ulcorner q -- - reverse p -- ulcorner q -- cycle - fi + lrcorner q -- urcorner q -- ulcorner q -- llcorner q -- + reverse p -- llcorner q -- cycle fi - endgroup + else : + if ypart start > ypart center p : + ulcorner q -- llcorner q -- lrcorner q -- urcorner q -- + reverse p -- urcorner q -- cycle + else : + llcorner q -- lrcorner q -- urcorner q -- ulcorner q -- + reverse p -- ulcorner q -- cycle + fi + fi + endgroup enddef ; boolean intersection_found ; secondarydef p intersection_point q = - begingroup + begingroup save x_, y_ ; (x_,y_) = p intersectiontimes q ; if x_<0 : - intersection_found := false ; - center p % origin + intersection_found := false ; + center p % origin else : - intersection_found := true ; - .5[point x_ of p, point y_ of q] + intersection_found := true ; + .5[point x_ of p, point y_ of q] fi - endgroup + endgroup enddef ; %D New, undocumented, experimental: vardef tensecircle (expr width, height, offset) = - (-width/2,-height/2) ... (0,-height/2-offset) ... - (+width/2,-height/2) ... (+width/2+offset,0) ... - (+width/2,+height/2) ... (0,+height/2+offset) ... - (-width/2,+height/2) ... (-width/2-offset,0) ... cycle + ((-width/2,-height/2) ... (0,-height/2-offset) ... + (+width/2,-height/2) ... (+width/2+offset,0) ... + (+width/2,+height/2) ... (0,+height/2+offset) ... + (-width/2,+height/2) ... (-width/2-offset,0) ... cycle) enddef ; +%vardef tensecircle (expr width, height, offset) = +% ((-width/2,-height/2)..(0,-height/2-offset)..(+width/2,-height/2) & +% (+width/2,-height/2)..(+width/2+offset,0)..(+width/2,+height/2) & +% (+width/2,+height/2)..(0,+height/2+offset)..(-width/2,+height/2) & +% (-width/2,+height/2)..(-width/2-offset,0)..(-width/2,-height/2)..cycle) +%enddef ; + vardef roundedsquare (expr width, height, offset) = - (offset,0) -- (width-offset,0) {right} .. - (width,offset) -- (width,height-offset) {up} .. - (width-offset,height) -- (offset,height) {left} .. - (0,height-offset) -- (0,offset) {down} .. cycle + ((offset,0)--(width-offset,0){right} .. + (width,offset)--(width,height-offset){up} .. + (width-offset,height)--(offset,height){left} .. + (0,height-offset)--(0,offset){down} .. cycle) enddef ; %D Some colors. +color cyan ; cyan = (0,1,1) ; +color magenta ; magenta = (1,0,1) ; +color yellow ; yellow = (1,1,0) ; + def colortype(expr c) = if cmykcolor c : cmykcolor elseif rgbcolor c : rgbcolor else : grayscale fi enddef ; - vardef whitecolor(expr c) = if cmykcolor c : (0,0,0,0) elseif rgbcolor c : (1,1,1) else : 1 fi enddef ; - vardef blackcolor(expr c) = if cmykcolor c : (0,0,0,1) elseif rgbcolor c : (0,0,0) else : 0 fi enddef ; @@ -852,74 +730,112 @@ enddef ; %D Well, this is the dangerous and naive version: def drawfill text t = - fill t ; - draw t ; + fill t ; + draw t ; enddef; %D This two step approach saves the path first, since it can %D be a function. Attributes must not be randomized. def drawfill expr c = - path _c_ ; _c_ := c ; - mfun_do_drawfill + path _c_ ; _c_ := c ; + do_drawfill enddef ; -def mfun_do_drawfill text t = - draw _c_ t ; - fill _c_ t ; +def do_drawfill text t = + draw _c_ t ; + fill _c_ t ; enddef; def undrawfill expr c = - drawfill c withcolor background % rather useless + drawfill c withcolor background enddef ; %D Moved from mp-char.mp -vardef paired primary d = - if pair d : d else : (d,d) fi +vardef paired (expr d) = + if pair d : d else : (d,d) fi +enddef ; + +vardef tripled (expr d) = + if color d : d else : (d,d,d) fi +enddef ; + +primarydef p enlarged d = + (p llmoved d -- p lrmoved d -- p urmoved d -- p ulmoved d -- cycle) +enddef; + +primarydef p llenlarged d = + (p llmoved d -- lrcorner p -- urcorner p -- ulcorner p -- cycle) +enddef ; + +primarydef p lrenlarged d = + (llcorner p -- p lrmoved d -- urcorner p -- ulcorner p -- cycle) enddef ; -vardef tripled primary d = - if color d : d else : (d,d,d) fi +primarydef p urenlarged d = + (llcorner p -- lrcorner p -- p urmoved d -- ulcorner p -- cycle) enddef ; -% maybe secondaries: +primarydef p ulenlarged d = + (llcorner p -- lrcorner p -- urcorner p -- p ulmoved d -- cycle) +enddef ; -primarydef p enlarged d = ( p llmoved d -- p lrmoved d -- p urmoved d -- p ulmoved d -- cycle ) enddef ; -primarydef p llenlarged d = ( p llmoved d -- lrcorner p -- urcorner p -- ulcorner p -- cycle ) enddef ; -primarydef p lrenlarged d = ( llcorner p -- p lrmoved d -- urcorner p -- ulcorner p -- cycle ) enddef ; -primarydef p urenlarged d = ( llcorner p -- lrcorner p -- p urmoved d -- ulcorner p -- cycle ) enddef ; -primarydef p ulenlarged d = ( llcorner p -- lrcorner p -- urcorner p -- p ulmoved d -- cycle ) enddef ; +primarydef p llmoved d = + ((llcorner p) shifted (-xpart paired(d),-ypart paired(d))) +enddef ; -primarydef p llmoved d = ( (llcorner p) shifted (-xpart paired(d),-ypart paired(d)) ) enddef ; -primarydef p lrmoved d = ( (lrcorner p) shifted (+xpart paired(d),-ypart paired(d)) ) enddef ; -primarydef p urmoved d = ( (urcorner p) shifted (+xpart paired(d),+ypart paired(d)) ) enddef ; -primarydef p ulmoved d = ( (ulcorner p) shifted (-xpart paired(d),+ypart paired(d)) ) enddef ; +primarydef p lrmoved d = + ((lrcorner p) shifted (+xpart paired(d),-ypart paired(d))) +enddef ; + +primarydef p urmoved d = + ((urcorner p) shifted (+xpart paired(d),+ypart paired(d))) +enddef ; + +primarydef p ulmoved d = + ((ulcorner p) shifted (-xpart paired(d),+ypart paired(d))) +enddef ; + +primarydef p leftenlarged d = + ((llcorner p) shifted (-d,0) -- lrcorner p -- + urcorner p -- (ulcorner p) shifted (-d,0) -- cycle) +enddef ; + +primarydef p rightenlarged d = + (llcorner p -- (lrcorner p) shifted (d,0) -- + (urcorner p) shifted (d,0) -- ulcorner p -- cycle) +enddef ; + +primarydef p topenlarged d = + (llcorner p -- lrcorner p -- + (urcorner p) shifted (0,d) -- (ulcorner p) shifted (0,d) -- cycle) +enddef ; -primarydef p leftenlarged d = ( (llcorner p) shifted (-d,0) -- lrcorner p -- urcorner p -- (ulcorner p) shifted (-d,0) -- cycle ) enddef ; -primarydef p rightenlarged d = ( llcorner p -- (lrcorner p) shifted (d,0) -- (urcorner p) shifted (d,0) -- ulcorner p -- cycle ) enddef ; -primarydef p topenlarged d = ( llcorner p -- lrcorner p -- (urcorner p) shifted (0,d) -- (ulcorner p) shifted (0,d) -- cycle ) enddef ; -primarydef p bottomenlarged d = ( llcorner p shifted (0,-d) -- lrcorner p shifted (0,-d) -- urcorner p -- ulcorner p -- cycle ) enddef ; +primarydef p bottomenlarged d = + (llcorner p shifted (0,-d) -- lrcorner p shifted (0,-d) -- + urcorner p -- ulcorner p -- cycle) +enddef ; %D Handy for testing/debugging: -primarydef p crossed d = ( +primarydef p crossed d = if pair p : - p shifted (-d, 0) -- p -- - p shifted ( 0,-d) -- p -- - p shifted (+d, 0) -- p -- - p shifted ( 0,+d) -- p -- cycle + (p shifted (-d, 0) -- p -- + p shifted ( 0,-d) -- p -- + p shifted (+d, 0) -- p -- + p shifted ( 0,+d) -- p -- cycle) else : - center p shifted (-d, 0) -- llcorner p -- - center p shifted ( 0,-d) -- lrcorner p -- - center p shifted (+d, 0) -- urcorner p -- - center p shifted ( 0,+d) -- ulcorner p -- cycle + (center p shifted (-d, 0) -- llcorner p -- + center p shifted ( 0,-d) -- lrcorner p -- + center p shifted (+d, 0) -- urcorner p -- + center p shifted ( 0,+d) -- ulcorner p -- cycle) fi -) enddef ; +enddef ; %D Also handy (math ladders): -vardef laddered primary p = % was expr +vardef laddered expr p = point 0 of p for i=1 upto length(p) : -- (xpart (point i of p), ypart (point (i-1) of p)) -- (point i of p) @@ -933,143 +849,182 @@ enddef ; % vardef topboundary primary p = (urcorner p -- ulcorner p) enddef ; % vardef leftboundary primary p = (ulcorner p -- llcorner p) enddef ; -vardef bottomboundary primary p = if pair p : p else : (llcorner p -- lrcorner p) fi enddef ; -vardef rightboundary primary p = if pair p : p else : (lrcorner p -- urcorner p) fi enddef ; -vardef topboundary primary p = if pair p : p else : (urcorner p -- ulcorner p) fi enddef ; -vardef leftboundary primary p = if pair p : p else : (ulcorner p -- llcorner p) fi enddef ; +vardef bottomboundary primary p = + if pair p : p else : (llcorner p -- lrcorner p) fi +enddef ; + +vardef rightboundary primary p = + if pair p : p else : (lrcorner p -- urcorner p) fi +enddef ; + +vardef topboundary primary p = + if pair p : p else : (urcorner p -- ulcorner p) fi +enddef ; + +vardef leftboundary primary p = + if pair p : p else : (ulcorner p -- llcorner p) fi +enddef ; %D Nice too: primarydef p superellipsed s = - superellipse ( - .5[lrcorner p,urcorner p], - .5[urcorner p,ulcorner p], - .5[ulcorner p,llcorner p], - .5[llcorner p,lrcorner p], - s - ) -enddef ; - -primarydef p squeezed s = ( - (llcorner p .. .5[llcorner p,lrcorner p] shifted ( 0, ypart paired(s)) .. lrcorner p) & - (lrcorner p .. .5[lrcorner p,urcorner p] shifted (-xpart paired(s), 0) .. urcorner p) & - (urcorner p .. .5[urcorner p,ulcorner p] shifted ( 0,-ypart paired(s)) .. ulcorner p) & - (ulcorner p .. .5[ulcorner p,llcorner p] shifted ( xpart paired(s), 0) .. llcorner p) & cycle -) enddef ; + superellipse + (.5[lrcorner p,urcorner p], + .5[urcorner p,ulcorner p], + .5[ulcorner p,llcorner p], + .5[llcorner p,lrcorner p], + s) +enddef ; -primarydef p randomshifted s = - begingroup ; - save ss ; pair ss ; - ss := paired(s) ; - p shifted (-.5xpart ss + uniformdeviate xpart ss,-.5ypart ss + uniformdeviate ypart ss) - endgroup +primarydef p squeezed s = + ((llcorner p .. .5[llcorner p,lrcorner p] shifted ( 0, ypart paired(s)) .. lrcorner p) & + (lrcorner p .. .5[lrcorner p,urcorner p] shifted (-xpart paired(s), 0) .. urcorner p) & + (urcorner p .. .5[urcorner p,ulcorner p] shifted ( 0,-ypart paired(s)) .. ulcorner p) & + (ulcorner p .. .5[ulcorner p,llcorner p] shifted ( xpart paired(s), 0) .. llcorner p) & cycle) enddef ; -primarydef p randomized s = ( - if path p : - for i=0 upto length(p)-1 : - ((point i of p) randomshifted s) .. controls - ((postcontrol i of p) randomshifted s) and - ((precontrol (i+1) of p) randomshifted s) .. - endfor - if cycle p : - cycle - else : - ((point length(p) of p) randomshifted s) - fi - elseif pair p : - p randomshifted s - elseif cmykcolor p : - if color s : - ((uniformdeviate cyanpart s) * cyanpart p, - (uniformdeviate magentapart s) * magentapart p, - (uniformdeviate yellowpart s) * yellowpart p, - (uniformdeviate blackpart s) * blackpart p) - elseif pair s : - ((xpart s + (uniformdeviate (ypart s - xpart s))) * p) - else : - ((uniformdeviate s) * p) - fi - elseif rgbcolor p : - if color s : - ((uniformdeviate redpart s) * redpart p, - (uniformdeviate greenpart s) * greenpart p, - (uniformdeviate bluepart s) * bluepart p) - elseif pair s : - ((xpart s + (uniformdeviate (ypart s - xpart s))) * p) - else : - ((uniformdeviate s) * p) - fi - elseif color p : - if color s : - ((uniformdeviate greypart s) * greypart p) - elseif pair s : - ((xpart s + (uniformdeviate (ypart s - xpart s))) * p) - else : - ((uniformdeviate s) * p) - fi +primarydef p randomshifted s = + begingroup ; save ss ; pair ss ; ss := paired(s) ; + p shifted (-.5xpart ss + uniformdeviate xpart ss, + -.5ypart ss + uniformdeviate ypart ss) + endgroup +enddef ; + +%primarydef p randomized s = +% for i=0 upto length(p)-1 : +% ((point i of p) randomshifted s) .. controls +% ((postcontrol i of p) randomshifted s) and +% ((precontrol (i+1) of p) randomshifted s) .. +% endfor cycle +%enddef ; + +primarydef p randomized s = + (if path p : + for i=0 upto length(p)-1 : + ((point i of p) randomshifted s) .. controls + ((postcontrol i of p) randomshifted s) and + ((precontrol (i+1) of p) randomshifted s) .. + endfor + if cycle p : + cycle else : - p + uniformdeviate s + ((point length(p) of p) randomshifted s) fi -) enddef ; + elseif pair p : + p randomshifted s + elseif cmykcolor p : + if color s : + (uniformdeviate cyanpart s * cyanpart p, + uniformdeviate magentapart s * magentapart p, + uniformdeviate yellowpart s * yellowpart p, + uniformdeviate blackpart s * blackpart p) + elseif pair s : + ((xpart s + uniformdeviate (ypart s - xpart s)) * p) + else : + (uniformdeviate s * p) + fi + elseif rgbcolor p : + if color s : + (uniformdeviate redpart s * redpart p, + uniformdeviate greenpart s * greenpart p, + uniformdeviate bluepart s * bluepart p) + elseif pair s : + ((xpart s + uniformdeviate (ypart s - xpart s)) * p) + else : + (uniformdeviate s * p) + fi + elseif color p : + if color s : + (uniformdeviate graypart s * graypart p) + elseif pair s : + ((xpart s + uniformdeviate (ypart s - xpart s)) * p) + else : + (uniformdeviate s * p) + fi + else : + p + uniformdeviate s + fi) +enddef ; %D Not perfect (alternative for interpath) vardef interpolated(expr s, p, q) = - save m ; numeric m ; - m := max(length(p),length(q)) ; - if path p : - for i=0 upto m-1 : - s[point (i /m) along p,point (i /m) along q] .. controls - s[postcontrol (i /m) along p,postcontrol (i /m) along q] and - s[precontrol ((i+1)/m) along p,precontrol ((i+1)/m) along q] .. - endfor - if cycle p : - cycle - else : - s[point infinity of p,point infinity of q] - fi - else : - a[p,q] - fi + save m ; m := max(length(p),length(q)) ; + (if path p : + for i=0 upto m-1 : + s[point (i /m) along p, + point (i /m) along q] .. controls + s[postcontrol (i /m) along p, + postcontrol (i /m) along q] and + s[precontrol ((i+1)/m) along p, + precontrol ((i+1)/m) along q] .. + endfor + if cycle p : + cycle + else : + s[point infinity of p, + point infinity of q] + fi + else : + a[p,q] + fi) enddef ; %D Interesting too: -primarydef p paralleled d = ( +% primarydef p parallel s = +% begingroup ; save q, b ; path q ; numeric b ; +% b := xpart (lrcorner p - llcorner p) ; +% q := p if b>0 : scaled ((b+2s)/b) fi ; +% (q shifted (center p-center q)) +% endgroup +% enddef ; + +%primarydef p parallel s = +% begingroup ; save q, w,h ; path q ; numeric w, h ; +% w := bbwidth(p) ; h := bbheight(p) ; +% q := p if (w>0) and (h>0) : +% xyscaled ((w+2*xpart paired(s))/w,(h+2*ypart paired(s))/h) fi ; +% (q shifted (center p-center q)) +% endgroup +%enddef ; + +primarydef p paralleled d = p shifted if d < 0 : - fi ((point abs(d) on (p rotatedaround(point 0 of p,90))) - point 0 of p) -) enddef ; +enddef ; vardef punked primary p = - point 0 of p for i=1 upto length(p)-1 : -- point i of p endfor - if cycle p : -- cycle else : -- point length(p) of p fi + (point 0 of p for i=1 upto length(p)-1 : -- point i of p endfor + if cycle p : -- cycle else : -- point length(p) of p fi) enddef ; vardef curved primary p = - point 0 of p for i=1 upto length(p)-1 : .. point i of p endfor - if cycle p : .. cycle else : .. point length(p) of p fi + (point 0 of p for i=1 upto length(p)-1 : .. point i of p endfor + if cycle p : .. cycle else : .. point length(p) of p fi) enddef ; primarydef p blownup s = - begingroup - save _p_ ; path _p_ ; - _p_ := p xysized (bbwidth(p)+2(xpart paired(s)),bbheight(p)+2(ypart paired(s))) ; - (_p_ shifted (center p - center _p_)) - endgroup + begingroup + save _p_ ; path _p_ ; _p_ := p xysized + (bbwidth (p)+2(xpart paired(s)), + bbheight(p)+2(ypart paired(s))) ; + (_p_ shifted (center p - center _p_)) + endgroup enddef ; %D Rather fundamental. % not yet ok -vardef leftrightpath(expr p, l) = % used in s-pre-19 - save q, r, t, b ; path q, r ; pair t, b ; - t := (ulcorner p -- urcorner p) intersection_point p ; - b := (llcorner p -- lrcorner p) intersection_point p ; - r := if xpart directionpoint t of p < 0 : reverse p else : p fi ; % r is needed, else problems when reverse is fed - q := r cutbefore if l: t else: b fi ; - q := q if xpart point 0 of r > 0 : & r fi cutafter if l: b else: t fi ; - q +def leftrightpath(expr p, l) = % used in s-pre-19 + save q, r, t, b ; path q, r ; pair t, b ; + t := (ulcorner p -- urcorner p) intersection_point p ; + b := (llcorner p -- lrcorner p) intersection_point p ; + r := if xpart directionpoint t of p < 0 : reverse p else : p fi ; % r is needed, else problems when reverse is fed + q := r cutbefore if l: t else: b fi ; + q := q if xpart point 0 of r > 0 : & + r fi cutafter if l: b else: t fi ; + q enddef ; vardef leftpath expr p = leftrightpath(p,true ) enddef ; @@ -1078,10 +1033,10 @@ vardef rightpath expr p = leftrightpath(p,false) enddef ; %D Drawoptions def saveoptions = - save _op_ ; def _op_ = enddef ; + save _op_ ; def _op_ = enddef ; enddef ; -%D Tracing. (not yet in lexer) +%D Tracing. let normaldraw = draw ; let normalfill = fill ; @@ -1091,6 +1046,7 @@ let normalfill = fill ; def normalfill expr c = addto currentpicture contour c _op_ enddef ; def normaldraw expr p = addto currentpicture if picture p: also p else: doublepath p withpen currentpen fi _op_ enddef ; + def drawlineoptions (text t) = def _lin_opt_ = t enddef ; enddef ; def drawpointoptions (text t) = def _pnt_opt_ = t enddef ; enddef ; def drawcontroloptions(text t) = def _ctr_opt_ = t enddef ; enddef ; @@ -1100,13 +1056,13 @@ def drawboundoptions (text t) = def _bnd_opt_ = t enddef ; enddef ; def drawpathoptions (text t) = def _pth_opt_ = t enddef ; enddef ; def resetdrawoptions = - drawlineoptions (withpen pencircle scaled 1pt withcolor .5white) ; - drawpointoptions (withpen pencircle scaled 4pt withcolor black) ; - drawcontroloptions(withpen pencircle scaled 2.5pt withcolor black) ; - drawlabeloptions () ; - draworiginoptions (withpen pencircle scaled 1pt withcolor .5white) ; - drawboundoptions (dashed evenly _ori_opt_) ; - drawpathoptions (withpen pencircle scaled 5pt withcolor .8white) ; + drawlineoptions (withpen pencircle scaled 1pt withcolor .5white) ; + drawpointoptions (withpen pencircle scaled 4pt withcolor black) ; + drawcontroloptions(withpen pencircle scaled 2.5pt withcolor black) ; + drawlabeloptions () ; + draworiginoptions (withpen pencircle scaled 1pt withcolor .5white) ; + drawboundoptions (dashed evenly _ori_opt_) ; + drawpathoptions (withpen pencircle scaled 5pt withcolor .8white) ; enddef ; resetdrawoptions ; @@ -1114,95 +1070,96 @@ resetdrawoptions ; %D Path. def drawpath expr p = - normaldraw p _pth_opt_ + normaldraw p _pth_opt_ enddef ; %D Arrow. vardef drawarrowpath expr p = - save autoarrows ; boolean autoarrows ; autoarrows := true ; - drawarrow p _pth_opt_ + save autoarrows ; boolean autoarrows ; autoarrows := true ; + drawarrow p _pth_opt_ enddef ; -% def drawarrowpath expr p = -% begingroup ; -% save autoarrows ; boolean autoarrows ; autoarrows := true ; -% save arrowpath ; path arrowpath ; arrowpath := p ; -% _drawarrowpath_ -% enddef ; +%def drawarrowpath expr p = +% begingroup ; +% save autoarrows ; boolean autoarrows ; autoarrows := true ; +% save arrowpath ; path arrowpath ; arrowpath := p ; +% _drawarrowpath_ +%enddef ; % -% def _drawarrowpath_ text t = -% drawarrow arrowpath _pth_opt_ t ; -% endgroup ; -% enddef ; +%def _drawarrowpath_ text t = +% drawarrow arrowpath _pth_opt_ t ; +% endgroup ; +%enddef ; def midarrowhead expr p = - arrowhead p cutafter (point length(p cutafter point .5 along p)+ahlength on p) + arrowhead p cutafter + (point length(p cutafter point .5 along p)+ahlength on p) enddef ; vardef arrowheadonpath (expr p, s) = - save autoarrows ; boolean autoarrows ; - autoarrows := true ; - set_ahlength(scaled ahfactor) ; % added - arrowhead p if s<1 : cutafter (point (s*arclength(p)+.5ahlength) on p) fi + save autoarrows ; boolean autoarrows ; autoarrows := true ; + set_ahlength(scaled ahfactor) ; % added + arrowhead p if s<1 : cutafter (point (s*arclength(p)+.5ahlength) on p) fi enddef ; %D Points. def drawpoint expr c = - if string c : - string _c_ ; - _c_ := "(" & c & ")" ; - dotlabel.urt(_c_, scantokens _c_) ; - drawdot scantokens _c_ - else : - dotlabel.urt("(" & decimal xpart c & "," & decimal ypart c & ")", c) ; - drawdot c - fi _pnt_opt_ + if string c : + string _c_ ; _c_ := "(" & c & ")" ; + dotlabel.urt(_c_, scantokens _c_) ; + drawdot scantokens _c_ + else : + dotlabel.urt("(" & decimal xpart c & "," & decimal ypart c & ")", c) ; + drawdot c + fi _pnt_opt_ enddef ; %D PathPoints. -def drawpoints expr c = path _c_ ; _c_ := c ; mfun_draw_points enddef ; -def drawcontrolpoints expr c = path _c_ ; _c_ := c ; mfun_draw_controlpoints enddef ; -def drawcontrollines expr c = path _c_ ; _c_ := c ; mfun_draw_controllines enddef ; -def drawpointlabels expr c = path _c_ ; _c_ := c ; mfun_draw_pointlabels enddef ; +def drawpoints expr c = path _c_ ; _c_ := c ; do_drawpoints enddef ; +def drawcontrolpoints expr c = path _c_ ; _c_ := c ; do_drawcontrolpoints enddef ; +def drawcontrollines expr c = path _c_ ; _c_ := c ; do_drawcontrollines enddef ; +def drawpointlabels expr c = path _c_ ; _c_ := c ; do_drawpointlabels enddef ; -def mfun_draw_points text t = - for _i_=0 upto length(_c_) : - normaldraw point _i_ of _c_ _pnt_opt_ t ; - endfor ; +def do_drawpoints text t = + for _i_=0 upto length(_c_) : + normaldraw point _i_ of _c_ _pnt_opt_ t ; + endfor ; enddef; -def mfun_draw_controlpoints text t = - for _i_=0 upto length(_c_) : - normaldraw precontrol _i_ of _c_ _ctr_opt_ t ; - normaldraw postcontrol _i_ of _c_ _ctr_opt_ t ; - endfor ; +def do_drawcontrolpoints text t = + for _i_=0 upto length(_c_) : + normaldraw precontrol _i_ of _c_ _ctr_opt_ t ; + normaldraw postcontrol _i_ of _c_ _ctr_opt_ t ; + endfor ; enddef; -def mfun_draw_controllines text t = - for _i_=0 upto length(_c_) : - normaldraw point _i_ of _c_ -- precontrol _i_ of _c_ _lin_opt_ t ; - normaldraw point _i_ of _c_ -- postcontrol _i_ of _c_ _lin_opt_ t ; - endfor ; +def do_drawcontrollines text t = + for _i_=0 upto length(_c_) : + normaldraw point _i_ of _c_ -- precontrol _i_ of _c_ _lin_opt_ t ; + normaldraw point _i_ of _c_ -- postcontrol _i_ of _c_ _lin_opt_ t ; + endfor ; enddef; boolean swappointlabels ; swappointlabels := false ; -def mfun_draw_pointlabels text t = - for _i_=0 upto length(_c_) : - pair _u_ ; _u_ := unitvector(direction _i_ of _c_) rotated if swappointlabels : - fi 90 ; - pair _p_ ; _p_ := (point _i_ of _c_) ; - _u_ := 12 * defaultscale * _u_ ; - normaldraw thelabel ( decimal _i_, _p_ shifted if cycle _c_ and (_i_=0) : - fi _u_ ) _lab_opt_ t ; - endfor ; +def do_drawpointlabels text t = + for _i_=0 upto length(_c_) : + pair _u_ ; _u_ := unitvector(direction _i_ of _c_) + rotated if swappointlabels : - fi 90 ; + pair _p_ ; _p_ := (point _i_ of _c_) ; + _u_ := 12 * defaultscale * _u_ ; + normaldraw thelabel ( decimal _i_, + _p_ shifted if cycle _c_ and (_i_=0) : - fi _u_ ) _lab_opt_ t ; + endfor ; enddef; %D Bounding box. def drawboundingbox expr p = - normaldraw boundingbox p _bnd_opt_ + normaldraw boundingbox p _bnd_opt_ enddef ; %D Origin. @@ -1210,8 +1167,10 @@ enddef ; numeric originlength ; originlength := .5cm ; def draworigin text t = - normaldraw (origin shifted (0, originlength) -- origin shifted (0,-originlength)) _ori_opt_ t ; - normaldraw (origin shifted ( originlength,0) -- origin shifted (-originlength,0)) _ori_opt_ t ; + normaldraw (origin shifted (0, originlength) -- + origin shifted (0,-originlength)) _ori_opt_ t ; + normaldraw (origin shifted ( originlength,0) -- + origin shifted (-originlength,0)) _ori_opt_ t ; enddef; %D Axis. @@ -1219,108 +1178,101 @@ enddef; numeric tickstep ; tickstep := 5mm ; numeric ticklength ; ticklength := 2mm ; -def drawxticks expr c = path _c_ ; _c_ := c ; mfun_draw_xticks enddef ; -def drawyticks expr c = path _c_ ; _c_ := c ; mfun_draw_yticks enddef ; -def drawticks expr c = path _c_ ; _c_ := c ; mfun_draw_ticks enddef ; +def drawxticks expr c = path _c_ ; _c_ := c ; do_drawxticks enddef ; +def drawyticks expr c = path _c_ ; _c_ := c ; do_drawyticks enddef ; +def drawticks expr c = path _c_ ; _c_ := c ; do_drawticks enddef ; % Adding eps prevents disappearance due to rounding errors. -def mfun_draw_xticks text t = - for i=0 step -tickstep until xpart llcorner _c_ - eps : - if (i<=xpart lrcorner _c_) : - normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ; - fi ; - endfor ; - for i=0 step tickstep until xpart lrcorner _c_ + eps : - if (i>=xpart llcorner _c_) : - normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ; - fi ; - endfor ; - normaldraw (llcorner _c_ -- ulcorner _c_) shifted (-xpart llcorner _c_,0) _ori_opt_ t ; +def do_drawxticks text t = + for i=0 step -tickstep until xpart llcorner _c_ - eps : + if (i<=xpart lrcorner _c_) : + normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ; + fi ; + endfor ; + for i=0 step tickstep until xpart lrcorner _c_ + eps : + if (i>=xpart llcorner _c_) : + normaldraw (i,-ticklength)--(i,ticklength) _ori_opt_ t ; + fi ; + endfor ; + normaldraw (llcorner _c_ -- ulcorner _c_) + shifted (-xpart llcorner _c_,0) _ori_opt_ t ; enddef ; -def mfun_draw_yticks text t = - for i=0 step -tickstep until ypart llcorner _c_ - eps : - if (i<=ypart ulcorner _c_) : - normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ; - fi ; - endfor ; - for i=0 step tickstep until ypart ulcorner _c_ + eps : - if (i>=ypart llcorner _c_) : - normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ; - fi ; - endfor ; - normaldraw (llcorner _c_ -- lrcorner _c_) shifted (0,-ypart llcorner _c_) _ori_opt_ t ; +def do_drawyticks text t = + for i=0 step -tickstep until ypart llcorner _c_ - eps : + if (i<=ypart ulcorner _c_) : + normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ; + fi ; + endfor ; + for i=0 step tickstep until ypart ulcorner _c_ + eps : + if (i>=ypart llcorner _c_) : + normaldraw (-ticklength,i)--(ticklength,i) _ori_opt_ t ; + fi ; + endfor ; + normaldraw (llcorner _c_ -- lrcorner _c_) + shifted (0,-ypart llcorner _c_) _ori_opt_ t ; enddef ; -def mfun_draw_ticks text t = - drawxticks _c_ t ; - drawyticks _c_ t ; +def do_drawticks text t = + drawxticks _c_ t ; + drawyticks _c_ t ; enddef ; %D All of it except axis. def drawwholepath expr p = - draworigin ; - drawpath p ; - drawcontrollines p ; - drawcontrolpoints p ; - drawpoints p ; - drawboundingbox p ; - drawpointlabels p ; + draworigin ; + drawpath p ; + drawcontrollines p ; + drawcontrolpoints p ; + drawpoints p ; + drawboundingbox p ; + drawpointlabels p ; enddef ; %D Tracing. def visualizeddraw expr c = - if picture c : normaldraw c else : path _c_ ; _c_ := c ; do_visualizeddraw fi + if picture c : normaldraw c else : path _c_ ; _c_ := c ; do_visualizeddraw fi enddef ; def visualizedfill expr c = - if picture c : normalfill c else : path _c_ ; _c_ := c ; do_visualizedfill fi + if picture c : normalfill c else : path _c_ ; _c_ := c ; do_visualizedfill fi enddef ; def do_visualizeddraw text t = - draworigin ; - drawpath _c_ t ; - drawcontrollines _c_ ; - drawcontrolpoints _c_ ; - drawpoints _c_ ; - drawboundingbox _c_ ; - drawpointlabels _c_ ; + draworigin ; + drawpath _c_ t ; + drawcontrollines _c_ ; + drawcontrolpoints _c_ ; + drawpoints _c_ ; + drawboundingbox _c_ ; + drawpointlabels _c_ ; enddef ; def do_visualizedfill text t = - if cycle _c_ : normalfill _c_ t fi ; - draworigin ; - drawcontrollines _c_ ; - drawcontrolpoints _c_ ; - drawpoints _c_ ; - drawboundingbox _c_ ; - drawpointlabels _c_ ; + if cycle _c_ : normalfill _c_ t fi ; + draworigin ; + drawcontrollines _c_ ; + drawcontrolpoints _c_ ; + drawpoints _c_ ; + drawboundingbox _c_ ; + drawpointlabels _c_ ; enddef ; def visualizepaths = - let fill = visualizedfill ; - let draw = visualizeddraw ; + let fill = visualizedfill ; + let draw = visualizeddraw ; enddef ; def naturalizepaths = - let fill = normalfill ; - let draw = normaldraw ; + let fill = normalfill ; + let draw = normaldraw ; enddef ; extra_endfig := extra_endfig & " naturalizepaths ; " ; -%D Nice tracer: - -def drawboundary primary p = - draw p dashed evenly withcolor white ; - draw p dashed oddly withcolor black ; - draw (- llcorner p) withpen pencircle scaled 3 withcolor white ; - draw (- llcorner p) withpen pencircle scaled 1.5 withcolor black ; -enddef ; - %D Also handy: extra_beginfig := extra_beginfig & " truecorners := 0 ; " ; % restores @@ -1335,57 +1287,46 @@ boolean autoarrows ; autoarrows := false ; numeric ahfactor ; ahfactor := 2.5 ; def set_ahlength (text t) = - % ahlength := (ahfactor*pen_size(_op_ t)) ; % _op_ added - % problem: _op_ can contain color so a no-go, we could apply the transform - % but i need to figure out the best way (fakepicture and take components). - ahlength := (ahfactor*pen_size(t)) ; +% ahlength := (ahfactor*pen_size(_op_ t)) ; % _op_ added +% problem: _op_ can contain color so a no-go, we could apply the transform +% but i need to figure out the best way (fakepicture and take components). + ahlength := (ahfactor*pen_size(t)) ; enddef ; vardef pen_size (text t) = - save p ; picture p ; p := nullpicture ; - addto p doublepath (top origin -- bot origin) t ; - (ypart urcorner p - ypart lrcorner p) + save p ; picture p ; p := nullpicture ; + addto p doublepath (top origin -- bot origin) t ; + (ypart urcorner p - ypart lrcorner p) enddef ; %D The next two macros are adapted versions of plain %D \METAPOST\ definitions. -vardef arrowpath expr p = % patch by Peter Rolf: supports squared pen and shifting (hh: maybe just use center of head as first) - (p cutafter makepath(pencircle scaled 2(ahlength*cosd(.5ahangle)) shifted point length p of p)) -enddef; - -% def _finarr text t = -% if autoarrows : set_ahlength (t) fi ; -% draw arrowpath _apth t ; % arrowpath added -% filldraw arrowhead _apth t ; -% enddef; - def _finarr text t = - if autoarrows : set_ahlength (t) fi ; - draw arrowpath _apth t ; % arrowpath added - fill arrowhead _apth t ; - draw arrowhead _apth t ; + if autoarrows : set_ahlength (t) fi ; + draw _apth t ; + filldraw arrowhead _apth t ; enddef; -def _finarr text t = - if autoarrows : set_ahlength (t) fi ; - draw arrowpath _apth t ; % arrowpath added - fill arrowhead _apth t ; - draw arrowhead _apth t undashed ; -enddef; +def _findarr text t = + if autoarrows : set_ahlength (t) fi ; + draw _apth t ; + fill arrowhead _apth withpen currentpen t ; + fill arrowhead reverse _apth withpen currentpen t ; +enddef ; %D Handy too ...... vardef pointarrow (expr pat, loc, len, off) = - save l, r, s, t ; path l, r ; numeric s ; pair t ; - t := if pair loc : loc else : point loc along pat fi ; - s := len/2 - off ; if s<=0 : s := 0 elseif s>len : s := len fi ; - r := pat cutbefore t ; - r := (r cutafter point (arctime s of r) of r) ; - s := len/2 + off ; if s<=0 : s := 0 elseif s>len : s := len fi ; - l := reverse (pat cutafter t) ; - l := (reverse (l cutafter point (arctime s of l) of l)) ; - (l..r) + save l, r, s, t ; path l, r ; numeric s ; pair t ; + t := if pair loc : loc else : point loc along pat fi ; + s := len/2 - off ; if s<=0 : s := 0 elseif s>len : s := len fi ; + r := pat cutbefore t ; + r := (r cutafter point (arctime s of r) of r) ; + s := len/2 + off ; if s<=0 : s := 0 elseif s>len : s := len fi ; + l := reverse (pat cutafter t) ; + l := (reverse (l cutafter point (arctime s of l) of l)) ; + (l..r) enddef ; def rightarrow (expr pat,tim,len) = pointarrow(pat,tim,len,-len) enddef ; @@ -1395,19 +1336,23 @@ def centerarrow (expr pat,tim,len) = pointarrow(pat,tim,len, 0) enddef ; %D The \type {along} and \type {on} operators can be used %D as follows: %D -%D \starttyping +%D \starttypen %D drawdot point .5 along somepath ; %D drawdot point 3cm on somepath ; -%D \stoptyping +%D \stoptypen %D %D The number denotes a percentage (fraction). primarydef pct along pat = % also negative - (arctime (pct * (arclength pat)) of pat) of pat + (arctime (pct * (arclength pat)) of pat) of pat enddef ; -primarydef len on pat = % no outer ( ) .. somehow fails - (arctime if len>0 : len else : (arclength(pat)+len) fi of pat) of pat +% primarydef len on pat = +% (arctime len of pat) of pat +% enddef ; + +primarydef len on pat = + (arctime if len>0 : len else : (arclength(pat)+len) fi of pat) of pat enddef ; % this cuts of a piece from both ends @@ -1420,55 +1365,69 @@ enddef ; % enddef ; tertiarydef pat cutends len = - begingroup - save tap ; path tap ; - tap := pat cutbefore (point (xpart paired(len)) on pat) ; - (tap cutafter (point -(ypart paired(len)) on tap)) - endgroup + begingroup ; save tap ; path tap ; + tap := pat cutbefore (point (xpart paired(len)) on pat) ; + (tap cutafter (point -(ypart paired(len)) on tap)) + endgroup enddef ; %D To be documented. path freesquare ; -freesquare := ( - (-1,0) -- (-1,-1) -- (0,-1) -- (+1,-1) -- - (+1,0) -- (+1,+1) -- (0,+1) -- (-1,+1) -- cycle -) scaled .5 ; +freesquare := ((-1,0)--(-1,-1)--(0,-1)--(+1,-1)-- + (+1,0)--(+1,+1)--(0,+1)--(-1,+1)--cycle) scaled .5 ; numeric freelabeloffset ; freelabeloffset := 3pt ; numeric freedotlabelsize ; freedotlabelsize := 3pt ; vardef thefreelabel (expr str, loc, ori) = - save s, p, q, l ; picture s ; path p, q ; pair l ; - interim labeloffset := freelabeloffset ; - s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ; - setbounds s to boundingbox s enlarged freelabeloffset ; - p := fullcircle scaled (2*length(loc-ori)) shifted ori ; - q := freesquare xyscaled (urcorner s - llcorner s) ; - l := point xpart (p intersectiontimes (ori--loc shifted (loc-ori))) of q ; - setbounds s to boundingbox s enlarged -freelabeloffset ; % new - % draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ; - (s shifted -l) + save s, p, q, l ; picture s ; path p, q ; pair l ; + interim labeloffset := freelabeloffset ; + s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ; + setbounds s to boundingbox s enlarged freelabeloffset ; + p := fullcircle scaled (2*length(loc-ori)) shifted ori ; + q := freesquare xyscaled (urcorner s - llcorner s) ; +% l := point (xpart (p intersectiontimes (ori--loc))) of q ; + l := point xpart (p intersectiontimes + (ori--((1+eps)*arclength(ori--loc)*unitvector(loc-ori)))) of q ; + setbounds s to boundingbox s enlarged -freelabeloffset ; % new + %draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ; + (s shifted -l) +enddef ; + +% better? + +vardef thefreelabel (expr str, loc, ori) = + save s, p, q, l ; picture s ; path p, q ; pair l ; + interim labeloffset := freelabeloffset ; + s := if string str : thelabel(str,loc) else : str shifted -center str shifted loc fi ; + setbounds s to boundingbox s enlarged freelabeloffset ; + p := fullcircle scaled (2*length(loc-ori)) shifted ori ; + q := freesquare xyscaled (urcorner s - llcorner s) ; + l := point xpart (p intersectiontimes (ori--loc shifted (loc-ori))) of q ; + setbounds s to boundingbox s enlarged -freelabeloffset ; % new + %draw boundingbox s shifted -l withpen pencircle scaled .5pt withcolor red ; + (s shifted -l) enddef ; vardef freelabel (expr str, loc, ori) = - draw thefreelabel(str,loc,ori) ; + draw thefreelabel(str,loc,ori) ; enddef ; vardef freedotlabel (expr str, loc, ori) = - interim linecap := rounded ; - draw loc withpen pencircle scaled freedotlabelsize ; - draw thefreelabel(str,loc,ori) ; + interim linecap:=rounded ; + draw loc withpen pencircle scaled freedotlabelsize ; + draw thefreelabel(str,loc,ori) ; enddef ; -%D \starttyping +%D \starttypen %D drawarrow anglebetween(line_a,line_b,somelabel) ; -%D \stoptyping +%D \stoptypen -newinternal angleoffset ; angleoffset := 0pt ; -newinternal anglelength ; anglelength := 20pt ; -newinternal anglemethod ; anglemethod := 1 ; +% angleoffset ; angleoffset := 0pt ; +numeric anglelength ; anglelength := 20pt ; +numeric anglemethod ; anglemethod := 1 ; % vardef anglebetween (expr a, b, str) = % path path string % save pointa, pointb, common, middle, offset ; @@ -1507,66 +1466,63 @@ newinternal anglemethod ; anglemethod := 1 ; % enddef ; vardef anglebetween (expr a, b, str) = % path path string - save pointa, pointb, common, middle, offset ; - pair pointa, pointb, common, middle, offset ; - save curve ; path curve ; - save where ; numeric where ; - if round point 0 of a = round point 0 of b : - common := point 0 of a ; - else : - common := a intersectionpoint b ; - fi ; - pointa := point anglelength on a ; - pointb := point anglelength on b ; - where := turningnumber (common--pointa--pointb--cycle) ; - middle := (reverse(common--pointa) rotatedaround (pointa,-where*90)) - intersection_point - (reverse(common--pointb) rotatedaround (pointb, where*90)) ; - if not intersection_found : - middle := point .5 along - ((reverse(common--pointa) rotatedaround (pointa,-where*90)) -- - ( (common--pointb) rotatedaround (pointb, where*90))) ; - fi ; - if anglemethod = 0 : - curve := pointa{unitvector(middle-pointa)}.. pointb; - middle := point .5 along curve ; - curve := common ; - elseif anglemethod = 1 : - curve := pointa{unitvector(middle-pointa)}.. pointb; - middle := point .5 along curve ; - elseif anglemethod = 2 : - middle := common rotatedaround(.5[pointa,pointb],180) ; - curve := pointa--middle--pointb ; - elseif anglemethod = 3 : - curve := pointa--middle--pointb ; - elseif anglemethod = 4 : - curve := pointa..controls middle..pointb ; - middle := point .5 along curve ; - fi ; - draw thefreelabel(str, middle, common) ; % withcolor black ; - curve + save pointa, pointb, common, middle, offset ; + pair pointa, pointb, common, middle, offset ; + save curve ; path curve ; + save where ; numeric where ; + if round point 0 of a = round point 0 of b : + common := point 0 of a ; + else : + common := a intersectionpoint b ; + fi ; + pointa := point anglelength on a ; + pointb := point anglelength on b ; + where := turningnumber (common--pointa--pointb--cycle) ; + middle := (reverse(common--pointa) rotatedaround (pointa,-where*90)) + intersection_point + (reverse(common--pointb) rotatedaround (pointb, where*90)) ; + if not intersection_found : + middle := point .5 along + ((reverse(common--pointa) rotatedaround (pointa,-where*90)) -- + ( (common--pointb) rotatedaround (pointb, where*90))) ; + fi ; + if anglemethod = 0 : + curve := pointa{unitvector(middle-pointa)}.. pointb; + middle := point .5 along curve ; + curve := common ; + elseif anglemethod = 1 : + curve := pointa{unitvector(middle-pointa)}.. pointb; + middle := point .5 along curve ; + elseif anglemethod = 2 : + middle := common rotatedaround(.5[pointa,pointb],180) ; + curve := pointa--middle--pointb ; + elseif anglemethod = 3 : + curve := pointa--middle--pointb ; + elseif anglemethod = 4 : + curve := pointa..controls middle..pointb ; + middle := point .5 along curve ; + fi ; + draw thefreelabel(str, middle, common) ; % withcolor black ; + curve enddef ; % Stack -picture mfun_current_picture_stack[] ; -numeric mfun_current_picture_depth ; - -mfun_current_picture_depth := 0 ; +picture currentpicturestack[] ; +numeric currentpicturedepth ; currentpicturedepth := 0 ; def pushcurrentpicture = - mfun_current_picture_depth := mfun_current_picture_depth + 1 ; - mfun_current_picture_stack[mfun_current_picture_depth] := currentpicture ; - currentpicture := nullpicture ; + currentpicturedepth := currentpicturedepth + 1 ; + currentpicturestack[currentpicturedepth] := currentpicture ; + currentpicture := nullpicture ; enddef ; def popcurrentpicture text t = % optional text - if mfun_current_picture_depth > 0 : - addto mfun_current_picture_stack[mfun_current_picture_depth] also currentpicture t ; - currentpicture := mfun_current_picture_stack[mfun_current_picture_depth] ; - mfun_current_picture_stack[mfun_current_picture_depth] := nullpicture ; - mfun_current_picture_depth := mfun_current_picture_depth - 1 ; - fi ; + if currentpicturedepth > 0 : + addto currentpicturestack[currentpicturedepth] also currentpicture t ; + currentpicture := currentpicturestack[currentpicturedepth] ; + currentpicturedepth := currentpicturedepth - 1 ; + fi ; enddef ; %D colorcircle(size, red, green, blue) ; @@ -1647,76 +1603,71 @@ enddef ; % popcurrentpicture ; % enddef ; -vardef colorcircle (expr size, red, green, blue) = % might move - save r, g, b, c, m, y, w ; save radius ; - path r, g, b, c, m, y, w ; numeric radius ; +vardef colorcircle (expr size, red, green, blue) = + save r, g, b, c, m, y, w ; save radius ; + path r, g, b, c, m, y, w ; numeric radius ; - radius := 5cm ; pickup pencircle scaled (radius/25) ; + radius := 5cm ; pickup pencircle scaled (radius/25) ; - transform t ; t := identity rotatedaround(origin,120) ; + transform t ; t := identity rotatedaround(origin,120) ; - r := fullcircle rotated 90 scaled radius shifted (0,radius/4) rotatedaround(origin,135) ; + r := fullcircle rotated 90 scaled radius + shifted (0,radius/4) rotatedaround(origin,135) ; - b := r transformed t ; g := b transformed t ; + b := r transformed t ; g := b transformed t ; - c := buildcycle(subpath(1,7) of g,subpath(1,7) of b) ; - y := c transformed t ; m := y transformed t ; + c := buildcycle(subpath(1,7) of g,subpath(1,7) of b) ; + y := c transformed t ; m := y transformed t ; - w := buildcycle(subpath(3,5) of r, subpath(3,5) of g,subpath(3,5) of b) ; + w := buildcycle(subpath(3,5) of r, subpath(3,5) of g,subpath(3,5) of b) ; - pushcurrentpicture ; + pushcurrentpicture ; - fill r withcolor red ; - fill g withcolor green ; - fill b withcolor blue ; - fill c withcolor white - red ; - fill m withcolor white - green ; - fill y withcolor white - blue ; - fill w withcolor white ; + fill r withcolor red ; + fill g withcolor green ; + fill b withcolor blue ; + fill c withcolor white-red ; + fill m withcolor white-green ; + fill y withcolor white-blue ; + fill w withcolor white ; - for i = r,g,b,c,m,y : draw i withcolor .5white ; endfor ; + for i = r,g,b,c,m,y : draw i withcolor .5white ; endfor ; - currentpicture := currentpicture xsized size ; + currentpicture := currentpicture xsized size ; - popcurrentpicture ; + popcurrentpicture ; enddef ; % penpoint (i,2) of somepath -> inner / outer point vardef penpoint expr pnt of p = - save n, d ; numeric n, d ; - (n,d) = if pair pnt : pnt else : (pnt,1) fi ; - (point n of p shifted ((penoffset direction n of p of currentpen) scaled d)) + save n, d ; numeric n, d ; + (n,d) = if pair pnt : pnt else : (pnt,1) fi ; + (point n of p shifted ((penoffset direction n of p of currentpen) scaled d)) enddef ; % nice: currentpicture := inverted currentpicture ; primarydef p uncolored c = - if color p : - c - p - else : - image ( - for i within p : - addto currentpicture - if stroked i or filled i : - if filled i : - contour - else : - doublepath - fi - pathpart i - dashed dashpart i withpen penpart i - else : - also i - fi - withcolor c-(redpart i, greenpart i, bluepart i) ; - endfor ; - ) + if color p : + c - p + else : + image + (for i within p : + addto currentpicture + if stroked i or filled i : + if filled i : contour else : doublepath fi pathpart i + dashed dashpart i withpen penpart i + else : + also i + fi + withcolor c-(redpart i, greenpart i, bluepart i) ; + endfor ; ) fi enddef ; vardef inverted primary p = - p uncolored white + (p uncolored white) enddef ; % primarydef p softened c = @@ -1741,54 +1692,45 @@ enddef ; % enddef ; primarydef p softened c = - begingroup - save cc ; color cc ; cc := tripled(c) ; - if color p : - (redpart cc * redpart p,greenpart cc * greenpart p, bluepart cc * bluepart p) - else : - image ( - for i within p : - addto currentpicture - if stroked i or filled i : - if filled i : - contour - else : - doublepath - fi - pathpart i - dashed dashpart i withpen penpart i - else : - also i - fi - withcolor (redpart cc * redpart i, greenpart cc * greenpart i, bluepart cc * bluepart i) ; - endfor ; - ) - fi - endgroup + begingroup + save cc ; color cc ; cc := tripled(c) ; + if color p : + (redpart cc * redpart p, + greenpart cc * greenpart p, + bluepart cc * bluepart p) + else : + image + (for i within p : + addto currentpicture + if stroked i or filled i : + if filled i : contour else : doublepath fi pathpart i + dashed dashpart i withpen penpart i + else : + also i + fi + withcolor (redpart cc * redpart i, + greenpart cc * greenpart i, + bluepart cc * bluepart i) ; + endfor ;) + fi + endgroup enddef ; vardef grayed primary p = - if color p : - tripled(.30redpart p+.59greenpart p+.11bluepart p) - else : - image ( - for i within p : - addto currentpicture - if stroked i or filled i : - if filled i : - contour - else : - doublepath - fi - pathpart i - dashed dashpart i - withpen penpart i - else : - also i - fi - withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ; - endfor ; - ) + if color p : + tripled(.30redpart p+.59greenpart p+.11bluepart p) + else : + image + (for i within p : + addto currentpicture + if stroked i or filled i : + if filled i : contour else : doublepath fi pathpart i + dashed dashpart i withpen penpart i + else : + also i + fi + withcolor tripled(.30redpart i+.59greenpart i+.11bluepart i) ; + endfor ; ) fi enddef ; @@ -1816,10 +1758,10 @@ def condition primary b = if b : "true" else : "false" fi enddef ; % undocumented primarydef p stretched s = - begingroup - save pp ; path pp ; pp := p xyscaled s ; - (pp shifted ((point 0 of p) - (point 0 of pp))) - endgroup + begingroup + save pp ; path pp ; pp := p xyscaled s ; + (pp shifted ((point 0 of p) - (point 0 of pp))) + endgroup enddef ; % primarydef p enlonged len = @@ -1891,40 +1833,40 @@ def yshifted expr dy = shifted(0,dy) enddef ; % def readfile (expr name) = - begingroup ; save ok ; boolean ok ; - if (readfrom (name) <> EOF) : - ok := false ; - elseif (readfrom (name) <> EOF) : - ok := false ; - else : - ok := true ; - fi ; - if not ok : - scantokens("input " & name & " ") ; - fi ; - closefrom (name) ; - endgroup ; + begingroup ; save ok ; boolean ok ; + if (readfrom (name) <> EOF) : + ok := false ; + elseif (readfrom (name) <> EOF) : + ok := false ; + else : + ok := true ; + fi ; + if not ok : + scantokens("input " & name & " ") ; + fi ; + closefrom (name) ; + endgroup ; enddef ; % permits redefinition of end in macro inner end ; -% this will be redone (when needed) using scripts and backend handling +% real fun let normalwithcolor = withcolor ; def remapcolors = - def withcolor primary c = normalwithcolor remappedcolor(c) enddef ; + def withcolor primary c = normalwithcolor remappedcolor(c) enddef ; enddef ; def normalcolors = - let withcolor = normalwithcolor ; + let withcolor = normalwithcolor ; enddef ; def resetcolormap = - color color_map[][][] ; - normalcolors ; + color color_map[][][] ; + normalcolors ; enddef ; resetcolormap ; @@ -1940,15 +1882,15 @@ def g_color primary c = greenpart c enddef ; def b_color primary c = bluepart c enddef ; def remapcolor(expr old, new) = - color_map[redpart old][greenpart old][bluepart old] := new ; + color_map[r_color old][g_color old][b_color old] := new ; enddef ; def remappedcolor(expr c) = - if known color_map[redpart c][greenpart c][bluepart c] : - color_map[redpart c][greenpart c][bluepart c] - else : - c - fi + if known color_map[r_color c][g_color c][b_color c] : + color_map[r_color c][g_color c][b_color c] + else : + c + fi enddef ; % def refill suffix c = do_repath (1) (c) enddef ; @@ -1988,11 +1930,11 @@ enddef ; % Thanks to Jens-Uwe Morawski for pointing out that we need % to treat bounded and clipped components as local pictures. -def recolor suffix p = p := repathed (0,p) enddef ; -def refill suffix p = p := repathed (1,p) enddef ; -def redraw suffix p = p := repathed (2,p) enddef ; -def retext suffix p = p := repathed (3,p) enddef ; -def untext suffix p = p := repathed (4,p) enddef ; +def recolor suffix p = p := repathed (0,p) enddef ; +def refill suffix p = p := repathed (1,p) enddef ; +def redraw suffix p = p := repathed (2,p) enddef ; +def retext suffix p = p := repathed (3,p) enddef ; +def untext suffix p = p := repathed (4,p) enddef ; % primarydef p recolored t = repathed(0,p) t enddef ; % primarydef p refilled t = repathed(1,p) t enddef ; @@ -2055,80 +1997,69 @@ def reprocess suffix p = p := repathed (22,p) enddef ; % no attributes % also 11 and 12 vardef repathed (expr mode, p) text t = - begingroup ; - if mode = 0 : - save withcolor ; - remapcolors ; + begingroup ; + if mode=0 : save withcolor ; remapcolors ; fi ; + save _p_, _pp_, _ppp_, _f_, _b_, _t_ ; + picture _p_, _pp_, _ppp_ ; color _f_ ; path _b_ ; transform _t_ ; + _b_ := boundingbox p ; _p_ := nullpicture ; + for i within p : + _f_ := (redpart i, greenpart i, bluepart i) ; + if bounded i : + _pp_ := repathed(mode,i) t ; + setbounds _pp_ to pathpart i ; + addto _p_ also _pp_ ; + elseif clipped i : + _pp_ := repathed(mode,i) t ; + clip _pp_ to pathpart i ; + addto _p_ also _pp_ ; + elseif stroked i : + if mode=21 : + _ppp_ := i ; % indirectness is needed + addto _p_ also image(scantokens(t & " pathpart _ppp_") + dashed dashpart i withpen penpart i + withcolor _f_ ; ) ; + elseif mode=22 : + _ppp_ := i ; % indirectness is needed + addto _p_ also image(scantokens(t & " pathpart _ppp_")) ; + else : + addto _p_ doublepath pathpart i + dashed dashpart i withpen penpart i + withcolor _f_ % (redpart i, greenpart i, bluepart i) + if mode=2 : t fi ; + fi ; + elseif filled i : + if mode=11 : + _ppp_ := i ; % indirectness is needed + addto _p_ also image(scantokens(t & " pathpart _ppp_") + withcolor _f_ ; ) ; + elseif mode=12 : + _ppp_ := i ; % indirectness is needed + addto _p_ also image(scantokens(t & " pathpart _ppp_")) ; + else : + addto _p_ contour pathpart i + withcolor _f_ + if (mode=1) and (_f_<>refillbackground) : t fi ; + fi ; + elseif textual i : % textpart i <> "" : + if mode <> 4 : + % transform _t_ ; + % (xpart _t_, xxpart _t_, xypart _t_) = (xpart i, xxpart i, xypart i) ; + % (ypart _t_, yypart _t_, yxpart _t_) = (ypart i, yypart i, yxpart i) ; + % addto _p_ also + % textpart i infont fontpart i % todo : other font + % transformed _t_ + % withpen penpart i + % withcolor _f_ + % if mode=3 : t fi ; + addto _p_ also i if mode=3 : t fi ; + fi ; + else : + addto _p_ also i ; fi ; - save _p_, _pp_, _ppp_, _f_, _b_, _t_ ; - picture _p_, _pp_, _ppp_ ; color _f_ ; path _b_ ; transform _t_ ; - _b_ := boundingbox p ; - _p_ := nullpicture ; - for i within p : - _f_ := (redpart i, greenpart i, bluepart i) ; - if bounded i : - _pp_ := repathed(mode,i) t ; - setbounds _pp_ to pathpart i ; - addto _p_ also _pp_ ; - elseif clipped i : - _pp_ := repathed(mode,i) t ; - clip _pp_ to pathpart i ; - addto _p_ also _pp_ ; - elseif stroked i : - if mode=21 : - _ppp_ := i ; % indirectness is needed - addto _p_ also image(scantokens(t & " pathpart _ppp_") - dashed dashpart i withpen penpart i - withcolor _f_ ; ) ; - elseif mode=22 : - _ppp_ := i ; % indirectness is needed - addto _p_ also image(scantokens(t & " pathpart _ppp_")) ; - else : - addto _p_ doublepath pathpart i - dashed dashpart i withpen penpart i - withcolor _f_ % (redpart i, greenpart i, bluepart i) - if mode = 2 : - t - fi ; - fi ; - elseif filled i : - if mode=11 : - _ppp_ := i ; % indirectness is needed - addto _p_ also image(scantokens(t & " pathpart _ppp_") - withcolor _f_ ; ) ; - elseif mode=12 : - _ppp_ := i ; % indirectness is needed - addto _p_ also image(scantokens(t & " pathpart _ppp_")) ; - else : - addto _p_ contour pathpart i - withcolor _f_ - if (mode=1) and (_f_<>refillbackground) : - t - fi ; - fi ; - elseif textual i : % textpart i <> "" : - if mode <> 4 : - % transform _t_ ; - % (xpart _t_, xxpart _t_, xypart _t_) = (xpart i, xxpart i, xypart i) ; - % (ypart _t_, yypart _t_, yxpart _t_) = (ypart i, yypart i, yxpart i) ; - % addto _p_ also - % textpart i infont fontpart i % todo : other font - % transformed _t_ - % withpen penpart i - % withcolor _f_ - % if mode=3 : t fi ; - addto _p_ also i - if mode=3 : - t - fi ; - fi ; - else : - addto _p_ also i ; - fi ; - endfor ; - setbounds _p_ to _b_ ; - _p_ - endgroup + endfor ; + setbounds _p_ to _b_ ; + _p_ + endgroup enddef ; % After a question of Denis on how to erase a z variable, Jacko @@ -2156,11 +2087,11 @@ enddef ; % which i decided to simplify to: def clearxy text s = - if false for $ := s : or true endfor : - forsuffixes $ := s : x$ := whatever ; y$ := whatever ; endfor ; - else : - save x, y ; - fi + if false for $ := s : or true endfor : + forsuffixes $ := s : x$ := whatever ; y$ := whatever ; endfor ; + else : + save x, y ; + fi enddef ; % so now we can say: clearxy ; as well as clearxy 1, 2, 3 ; @@ -2172,68 +2103,48 @@ enddef ; % show x0 ; z0 = (30,30) ; primarydef p smoothed d = - (p llmoved (-xpart paired(d),0) -- p lrmoved (-xpart paired(d),0) {right} .. - p lrmoved (0,-ypart paired(d)) -- p urmoved (0,-ypart paired(d)) {up} .. - p urmoved (-xpart paired(d),0) -- p ulmoved (-xpart paired(d),0) {left} .. - p ulmoved (0,-ypart paired(d)) -- p llmoved (0,-ypart paired(d)) {down} .. cycle) + (p llmoved (-xpart paired(d),0) -- p lrmoved (-xpart paired(d),0) {right} .. + p lrmoved (0,-ypart paired(d)) -- p urmoved (0,-ypart paired(d)) {up} .. + p urmoved (-xpart paired(d),0) -- p ulmoved (-xpart paired(d),0) {left} .. + p ulmoved (0,-ypart paired(d)) -- p llmoved (0,-ypart paired(d)) {down} .. cycle) enddef ; primarydef p cornered c = - ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) -- - for i=1 upto length(p) : - (point i-1 of p) shifted (c*(unitvector(point i of p - point i-1 of p))) -- - (point i of p) shifted (c*(unitvector(point i-1 of p - point i of p))) .. - controls point i of p .. - endfor cycle) + ((point 0 of p) shifted (c*(unitvector(point 1 of p - point 0 of p))) -- + for i=1 upto length(p) : + (point i-1 of p) shifted (c*(unitvector(point i of p - point i-1 of p))) -- + (point i of p) shifted (c*(unitvector(point i-1 of p - point i of p))) .. + controls point i of p .. + endfor cycle) enddef ; % cmyk color support vardef cmyk(expr c,m,y,k) = - (1-c-k,1-m-k,1-y-k) + (1-c-k,1-m-k,1-y-k) enddef ; % handy -% vardef bbwidth (expr p) = % vardef width_of primary p = -% if known p : -% if path p or picture p : -% xpart (lrcorner p - llcorner p) -% else : -% 0 -% fi -% else : -% 0 -% fi -% enddef ; - -vardef bbwidth primary p = - if unknown p : - 0 - elseif path p or picture p : - xpart (lrcorner p - llcorner p) +vardef bbwidth (expr p) = % vardef width_of primary p = + if known p : + if path p or picture p : + xpart (lrcorner p - llcorner p) + else : + 0 + fi else : 0 fi enddef ; -% vardef bbheight (expr p) = % vardef heigth_of primary p = -% if known p : -% if path p or picture p : -% ypart (urcorner p - lrcorner p) -% else : -% 0 -% fi -% else : -% 0 -% fi -% enddef ; - -vardef bbheight primary p = - if unknown p : - 0 - elseif path p or picture p : - ypart (urcorner p - lrcorner p) +vardef bbheight (expr p) = % vardef heigth_of primary p = + if known p : + if path p or picture p : + ypart (urcorner p - lrcorner p) + else : + 0 + fi else : 0 fi @@ -2242,87 +2153,122 @@ enddef ; color nocolor ; numeric noline ; % both unknown signals def dowithpath (expr p, lw, lc, bc) = - if known p : - if known bc : - fill p withcolor bc ; - fi ; - if known lw and known lc : - draw p withpen pencircle scaled lw withcolor lc ; - elseif known lw : - draw p withpen pencircle scaled lw ; - elseif known lc : - draw p withcolor lc ; - fi ; + if known p : + if known bc : + fill p withcolor bc ; + fi ; + if known lw and known lc : + draw p withpen pencircle scaled lw withcolor lc ; + elseif known lw : + draw p withpen pencircle scaled lw ; + elseif known lc : + draw p withcolor lc ; fi ; + fi ; enddef ; % result from metafont discussion list (denisr/boguslawj) -def [[ = [ [ enddef ; def [[[ = [ [ [ enddef ; -def ]] = ] ] enddef ; def ]]] = ] ] ] enddef ; +def ]] = ] ] enddef ; def ]]] = ] ] ] enddef ; +def [[ = [ [ enddef ; def [[[ = [ [ [ enddef ; -let == = = ; - -% added +% not perfect, but useful since it removes redundant points. -picture oddly ; % evenly already defined +% vardef dostraightened(expr sign, p) = +% if length(p)>2 : % was 1, but straight lines are ok +% save pp ; path pp ; +% pp := point 0 of p ; +% for i=1 upto length(p)-1 : +% if round(point i of p) <> round(point length(pp) of pp) : +% pp := pp -- point i of p ; +% fi ; +% endfor ; +% save n, ok ; numeric n ; boolean ok ; +% n := length(pp) ; ok := false ; +% if n>2 : +% for i=0 upto n : % evt hier ook round +% if unitvector(round(point i of pp - +% point if i=0 : n else : i-1 fi of pp)) <> +% sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp - +% point i of pp)) : +% if ok : -- else : ok := true ; fi point i of pp +% fi +% endfor +% if ok and (cycle p) : -- cycle fi +% else : +% pp +% fi +% else : +% p +% fi +% enddef ; -evenly := dashpattern(on 3 off 3) ; -oddly := dashpattern(off 3 on 3) ; +% vardef simplified expr p = +% (reverse dostraightened(+1,dostraightened(+1,reverse p))) +% enddef ; -% not perfect, but useful since it removes redundant points. +% vardef unspiked expr p = +% (reverse dostraightened(-1,dostraightened(-1,reverse p))) +% enddef ; -vardef mfun_straightened(expr sign, p) = - save _p_, _q_ ; path _p_, _q_ ; - _p_ := p ; - forever : - _q_ := mfun_do_straightened(sign, _p_) ; - exitif length(_p_) = length(_q_) ; - _p_ := _q_ ; +% simplified : remove same points as well as redundant points +% unspiked : remove same points as well as areas with zero distance + +vardef dostraightened(expr sign, p) = + save _p_, _q_ ; path _p_, _q_ ; + _p_ := p ; + forever : + _q_ := dodostraightened(sign, _p_) ; + exitif length(_p_) = length(_q_) ; + _p_ := _q_ ; + endfor ; + _q_ +enddef ; + +vardef dodostraightened(expr sign, p) = + if length(p)>2 : % was 1, but straight lines are ok + save pp ; path pp ; + pp := point 0 of p ; + for i=1 upto length(p)-1 : + if round(point i of p) <> round(point length(pp) of pp) : + pp := pp -- point i of p ; + fi ; endfor ; - _q_ -enddef ; - -vardef mfun_do_straightened(expr sign, p) = - if length(p)>2 : % was 1, but straight lines are ok - save pp ; path pp ; - pp := point 0 of p ; - for i=1 upto length(p)-1 : - if round(point i of p) <> round(point length(pp) of pp) : - pp := pp -- point i of p ; - fi ; - endfor ; - save n, ok ; numeric n ; boolean ok ; - n := length(pp) ; ok := false ; - if n>2 : - for i=0 upto n : % evt hier ook round - if unitvector(round(point i of pp - point if i=0 : n else : i-1 fi of pp)) <> - sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp - point i of pp)) : - if ok : - -- - else : - ok := true ; - fi point i of pp - fi - endfor - if ok and (cycle p) : - -- cycle - fi - else : - pp + save n, ok ; numeric n ; boolean ok ; + n := length(pp) ; ok := false ; + if n>2 : + for i=0 upto n : % evt hier ook round + if unitvector(round(point i of pp - + point if i=0 : n else : i-1 fi of pp)) <> + sign * unitvector(round(point if i=n : 0 else : i+1 fi of pp - + point i of pp)) : + if ok : -- else : ok := true ; fi point i of pp fi + endfor + if ok and (cycle p) : -- cycle fi else : - p + pp fi + else : + p + fi enddef ; -vardef simplified expr p = ( - reverse mfun_straightened(+1,mfun_straightened(+1,reverse p)) -) enddef ; +% vardef simplified expr p = +% dostraightened(+1,p) +% enddef ; + +% vardef unspiked expr p = +% dostraightened(-1,p) +% enddef ; + +vardef simplified expr p = + (reverse dostraightened(+1,dostraightened(+1,reverse p))) +enddef ; -vardef unspiked expr p = ( - reverse mfun_straightened(-1,mfun_straightened(-1,reverse p)) -) enddef ; +vardef unspiked expr p = + (reverse dostraightened(-1,dostraightened(-1,reverse p))) +enddef ; % path p ; % p := (2cm,1cm) -- (2cm,1cm) -- (2cm,1cm) -- (3cm,1cm) -- @@ -2343,197 +2289,213 @@ vardef unspiked expr p = ( path originpath ; originpath := origin -- cycle ; vardef unitvector primary z = - if abs z = abs origin : z else : z/abs z fi + if abs z = abs origin : z else : z/abs z fi enddef; % also new -% vardef anchored@#(expr p, z) = % maybe use the textext variant -% p shifted (z + (labxf@#*lrcorner p + labyf@#*ulcorner p + (1-labxf@#-labyf@#)*llcorner p)) -% enddef ; +vardef anchored@#(expr p, z) = + p shifted (z + (labxf@#*lrcorner p + labyf@#*ulcorner p + + (1-labxf@#-labyf@#)*llcorner p)) +enddef ; % epsed(1.2345) vardef epsed (expr e) = - e if e>0 : + eps elseif e<0 : - eps fi + e if e>0 : + eps elseif e<0 : - eps fi enddef ; % handy def withgray primary g = - withcolor (g,g,g) + withcolor (g,g,g) enddef ; % for metafun -if unknown darkred : color darkred ; darkred := .625(1,0,0) fi ; -if unknown darkgreen : color darkgreen ; darkgreen := .625(0,1,0) fi ; -if unknown darkblue : color darkblue ; darkblue := .625(0,0,1) fi ; -if unknown darkcyan : color darkcyan ; darkcyan := .625(0,1,1) fi ; -if unknown darkmagenta : color darkmagenta ; darkmagenta := .625(1,0,1) fi ; -if unknown darkyellow : color darkyellow ; darkyellow := .625(1,1,0) fi ; -if unknown darkgray : color darkgray ; darkgray := .625(1,1,1) fi ; -if unknown lightgray : color lightgray ; lightgray := .875(1,1,1) fi ; +if unknown darkred : color darkred ; darkred := .625(1,0,0) fi ; +if unknown darkyellow : color darkyellow ; darkyellow := .625(1,1,0) fi ; +if unknown darkgray : color darkgray ; darkgray := .625(1,1,1) fi ; +if unknown lightgray : color lightgray ; lightgray := .875(1,1,1) fi ; % an improved plain mp macro vardef center primary p = - if pair p : - p - else : - .5[llcorner p, urcorner p] - fi + if pair p : p else : .5[llcorner p, urcorner p] fi enddef; % new, yet undocumented vardef rangepath (expr p, d, a) = - if length p>0 : - (d*unitvector(direction 0 of p) rotated a) shifted point 0 of p - -- p -- - (d*unitvector(direction length(p) of p) rotated a) shifted point length(p) of p - else : - p - fi + (if length p>0 : + (d*unitvector(direction 0 of p) rotated a) + shifted point 0 of p + -- p -- + (d*unitvector(direction length(p) of p) rotated a) + shifted point length(p) of p + else : + p + fi) enddef ; % under construction -vardef straightpath (expr a, b, method) = - if (method<1) or (method>6) : - (a--b) - elseif method = 1 : - (a -- - if xpart a > xpart b : - if ypart a > ypart b : - (xpart b,ypart a) -- - elseif ypart a < ypart b : - (xpart a,ypart b) -- - fi - elseif xpart a < xpart b : - if ypart a > ypart b : - (xpart a,ypart b) -- - elseif ypart a < ypart b : - (xpart b,ypart a) -- - fi - fi - b) - elseif method = 3 : - (a -- - if xpart a > xpart b : - (xpart b,ypart a) -- - elseif xpart a < xpart b : - (xpart a,ypart b) -- - fi - b) - elseif method = 5 : - (a -- - if ypart a > ypart b : - (xpart b,ypart a) -- - elseif ypart a < ypart b : - (xpart a,ypart b) -- - fi - b) - else : - (reverse straightpath(b,a,method-1)) +vardef straightpath(expr a, b, method) = + if (method<1) or (method>6) : + (a--b) + elseif method = 1 : + (a -- + if xpart a > xpart b : + if ypart a > ypart b : + (xpart b,ypart a) -- + elseif ypart a < ypart b : + (xpart a,ypart b) -- + fi + elseif xpart a < xpart b : + if ypart a > ypart b : + (xpart a,ypart b) -- + elseif ypart a < ypart b : + (xpart b,ypart a) -- + fi fi + b) + elseif method = 3 : + (a -- + if xpart a > xpart b : + (xpart b,ypart a) -- + elseif xpart a < xpart b : + (xpart a,ypart b) -- + fi + b) + elseif method = 5 : + (a -- + if ypart a > ypart b : + (xpart b,ypart a) -- + elseif ypart a < ypart b : + (xpart a,ypart b) -- + fi + b) + else : + (reverse straightpath(b,a,method-1)) + fi enddef ; % handy for myself def addbackground text t = - begingroup ; - save p, b ; picture p ; path b ; - b := boundingbox currentpicture ; - p := currentpicture ; currentpicture := nullpicture ; - fill b t ; - setbounds currentpicture to b ; - addto currentpicture also p ; - endgroup ; + begingroup ; save p, b ; picture p ; path b ; + b := boundingbox currentpicture ; + p := currentpicture ; currentpicture := nullpicture ; + fill b t ; setbounds currentpicture to b ; addto currentpicture also p ; + endgroup ; enddef ; % makes a (line) into an infinite one (handy for calculating % intersection points vardef infinite expr p = - (-infinity*unitvector(direction 0 of p) + (-infinity*unitvector(direction 0 of p) shifted point 0 of p - -- p -- - +infinity*unitvector(direction length(p) of p) - shifted point length(p) of p) + -- p -- + +infinity*unitvector(direction length(p) of p) + shifted point length(p) of p) enddef ; % obscure macros: create var from string and replace - and : -% (needed for process color id's) .. will go away +% (needed for process color id's) -string mfun_clean_ascii[] ; +string _clean_ascii_[] ; def register_dirty_chars(expr str) = for i = 0 upto length(str)-1 : - mfun_clean_ascii[ASCII substring(i,i+1) of str] := "_" ; + _clean_ascii_[ASCII substring(i,i+1) of str] := "_" ; endfor ; enddef ; register_dirty_chars("+-*/:;., ") ; vardef cleanstring (expr s) = - save ss ; string ss, si ; ss = "" ; save i ; - for i=0 upto length(s) : - si := substring(i,i+1) of s ; - ss := ss & if known mfun_clean_ascii[ASCII si] : mfun_clean_ascii[ASCII si] else : si fi ; - endfor ; - ss + save ss ; string ss, si ; ss = "" ; save i ; + for i=0 upto length(s) : + si := substring(i,i+1) of s ; + ss := ss & if known _clean_ascii_[ASCII si] : _clean_ascii_[ASCII si] else : si fi ; + endfor ; + ss enddef ; vardef asciistring (expr s) = - save ss ; string ss, si ; ss = "" ; save i ; - for i=0 upto length(s) : - si := substring(i,i+1) of s ; - if (ASCII si >= ASCII "0") and (ASCII si <= ASCII "9") : - ss := ss & char(scantokens(si) + ASCII "A") ; - else : - ss := ss & si ; - fi ; - endfor ; - ss + save ss ; string ss, si ; ss = "" ; save i ; + for i=0 upto length(s) : + si := substring(i,i+1) of s ; + if (ASCII si >= ASCII "0") and (ASCII si <= ASCII "9") : + ss := ss & char(scantokens(si) + ASCII "A") ; + else : + ss := ss & si ; + fi ; + endfor ; + ss enddef ; vardef setunstringed (expr s, v) = - scantokens(cleanstring(s)) := v ; + scantokens(cleanstring(s)) := v ; +enddef ; + +vardef setunstringed (expr s, v) = + scantokens(cleanstring(s)) := v ; enddef ; vardef getunstringed (expr s) = - scantokens(cleanstring(s)) + scantokens(cleanstring(s)) enddef ; vardef unstringed (expr s) = - expandafter known scantokens(cleanstring(s)) + expandafter known scantokens(cleanstring(s)) +enddef ; + +% new + +% vardef colorpart(expr i) = +% (redpart i, greenpart i,bluepart i) +% enddef ; + +vardef colorpart(expr c) = + if colormodel c = 3 : + graypart c + elseif colormodel c = 5 : + (redpart c,greenpart c,bluepart c) + elseif colormodel c = 7 : + (cyanpart c,magentapart c,yellowpart c,blackpart c) + fi enddef ; % for david arnold: % showgrid(-5,10,1cm,-10,10,1cm); -def showgrid (expr MinX, MaxX, DeltaX, MinY, MaxY, DeltaY) = % will move - begingroup - save size ; numeric size ; size := 2pt ; +def showgrid (expr MinX, MaxX, DeltaX, MinY, MaxY, DeltaY)= + begingroup + save defaultfont, defaultscale, size ; + string defaultfont ; defaultfont := "cmtt10"; % i.e. infofont + numeric defaultscale ; defaultscale := 8pt / fontsize defaultfont; + numeric size ; size := 2pt ; for x=MinX upto MaxX : - for y=MinY upto MaxY : - draw (x*DeltaX, y*DeltaY) withpen pencircle scaled - if (x mod 5 = 0) and (y mod 5 = 0) : - 1.5size withcolor .50white - else : - size withcolor .75white - fi ; - endfor ; + for y=MinY upto MaxY : + draw (x*DeltaX, y*DeltaY) + withpen pencircle scaled + if (x mod 5 = 0) and (y mod 5 = 0) : + 1.5size withcolor .50white + else : + size withcolor .75white + fi ; + endfor ; endfor ; for x=MinX upto MaxX: - label.bot(textext("\infofont " & decimal x), (x*DeltaX,-size)) ; + label.bot(decimal x, (x*DeltaX,-size)); endfor ; for y=MinY upto MaxY: - label.lft(textext("\infofont " & decimal y), (-size,y*DeltaY)) ; + label.lft(decimal y, (-size,y*DeltaY)) ; endfor ; - endgroup + endgroup enddef; % new, handy for: @@ -2563,24 +2525,26 @@ enddef; % % \useMPgraphic{map}{n=3} -vardef phantom (text t) = % to be checked - picture _p_ ; - _p_ := image(t) ; - addto _p_ also currentpicture ; - setbounds currentpicture to boundingbox _p_ ; +vardef phantom (text t) = + picture _p_ ; _p_ := image(t) ; addto _p_ also currentpicture ; + setbounds currentpicture to boundingbox _p_ ; enddef ; vardef c_phantom (expr b) (text t) = - if b : - picture _p_ ; - _p_ := image(t) ; - addto _p_ also currentpicture ; - setbounds currentpicture to boundingbox _p_ ; - else : - t ; - fi ; + if b : + picture _p_ ; _p_ := image(t) ; addto _p_ also currentpicture ; + setbounds currentpicture to boundingbox _p_ ; + else : + t ; + fi ; enddef ; +% mark paths (for external progs to split) + +% def somepath(expr p) +% p +% enddef ; + %D Handy: def break = @@ -2589,228 +2553,27 @@ enddef ; %D New too: -primarydef p xstretched w = ( - p if (bbwidth (p)>0) and (w>0) : xscaled (w/bbwidth (p)) fi -) enddef ; - -primarydef p ystretched h = ( - p if (bbheight(p)>0) and (h>0) : yscaled (h/bbheight(p)) fi -) enddef ; - -primarydef p snapped s = - hide ( - if path p : - forever : - exitif (bbheight(p) <= s) and (bbwidth(p) <= s) ; - p := p scaled (1/2) ; - endfor ; - elseif numeric p : - forever : - exitif p <= s ; - p := p scaled (1/2) ; - endfor ; - fi ; - ) - p +primarydef p xstretched w = + (p if (bbwidth (p)>0) and (w>0) : xscaled (w/bbwidth (p)) fi) enddef ; -% vardef somecolor = (1,1,0,0) enddef ; - -% fill OverlayBox withcolor (rcomponent somecolor,gcomponent somecolor,bcomponent somecolor) ; -% fill OverlayBox withcolor (ccomponent somecolor,mcomponent somecolor,ycomponent somecolor,bcomponent somecolor) ; - -% This could be standard mplib 2 behaviour: - -vardef rcomponent expr p = if rgbcolor p : redpart p elseif cmykcolor p : 1 - cyanpart p else : p fi enddef ; -vardef gcomponent expr p = if rgbcolor p : greenpart p elseif cmykcolor p : 1 - magentapart p else : p fi enddef ; -vardef bcomponent expr p = if rgbcolor p : bluepart p elseif cmykcolor p : 1 - yellowpart p else : p fi enddef ; -vardef ccomponent expr p = if cmykcolor p : cyanpart p elseif rgbcolor p : 1 - redpart p else : p fi enddef ; -vardef mcomponent expr p = if cmykcolor p : magentapart p elseif rgbcolor p : 1 - greenpart p else : p fi enddef ; -vardef ycomponent expr p = if cmykcolor p : yellowpart p elseif rgbcolor p : 1 - bluepart p else : p fi enddef ; -vardef bcomponent expr p = if cmykcolor p : blackpart p elseif rgbcolor p : 0 else : p fi enddef ; - -% draw image (...) ... ; % prescripts prepended to first, postscripts appended to last -% draw decorated (...) ... ; % prescripts prepended to each, postscripts appended to each -% draw redecorated (...) ... ; % prescripts assigned to each, postscripts assigned to each -% draw undecorated (...) ... ; % following properties are ignored, existing properties are kept -% -% draw decorated ( -% draw fullcircle scaled 20cm withpen pencircle scaled 20mm withcolor red withtransparency (1,.40) ; -% draw fullcircle scaled 15cm withpen pencircle scaled 15mm withcolor green withtransparency (1,.30) ; -% draw fullcircle scaled 10cm withpen pencircle scaled 10mm withcolor blue withtransparency (1,.20) ; -% ) -% withcolor blue -% withtransparency (1,.125) % selectively applied -% withpen pencircle scaled 10mm -% ; - -% vardef image (text imagedata) = % already defined -% save currentpicture ; -% picture currentpicture ; -% currentpicture := nullpicture ; -% imagedata ; -% currentpicture -% enddef ; - -vardef undecorated (text imagedata) text decoration = - save currentpicture ; - picture currentpicture ; - currentpicture := nullpicture ; - imagedata ; - currentpicture -enddef ; - - -if metapostversion < 1.770 : - - vardef decorated (text imagedata) text decoration = - save mfun_decorated_path, currentpicture ; - picture mfun_decorated_path, currentpicture ; - currentpicture := nullpicture ; - imagedata ; - mfun_decorated_path := currentpicture ; - currentpicture := nullpicture ; - for i within mfun_decorated_path : - addto currentpicture - if stroked i : - doublepath pathpart i - dashed dashpart i - withpen penpart i - withcolor colorpart i - decoration - elseif filled i : - contour pathpart i - withpen penpart i - withcolor colorpart i - decoration - elseif textual i : - also i - withcolor colorpart i - decoration - else : - also i - fi - ; - endfor ; - currentpicture - enddef ; - -else: - - vardef decorated (text imagedata) text decoration = - save mfun_decorated_path, currentpicture ; - picture mfun_decorated_path, currentpicture ; - currentpicture := nullpicture ; - imagedata ; - mfun_decorated_path := currentpicture ; - currentpicture := nullpicture ; - for i within mfun_decorated_path : - addto currentpicture - if stroked i : - doublepath pathpart i - dashed dashpart i - withpen penpart i - withcolor colorpart i - withprescript prescriptpart i - withpostscript postscriptpart i - decoration - elseif filled i : - contour pathpart i - withpen penpart i - withcolor colorpart i - withprescript prescriptpart i - withpostscript postscriptpart i - decoration - elseif textual i : - also i - withcolor colorpart i - withprescript prescriptpart i - withpostscript postscriptpart i - decoration - else : - also i - fi - ; - endfor ; - currentpicture - enddef ; - -fi ; - -vardef redecorated (text imagedata) text decoration = - save mfun_decorated_path, currentpicture ; - picture mfun_decorated_path, currentpicture ; - currentpicture := nullpicture ; - imagedata ; - mfun_decorated_path := currentpicture ; - currentpicture := nullpicture ; - for i within mfun_decorated_path : - addto currentpicture - if stroked i : - doublepath pathpart i - dashed dashpart i - withpen penpart i - decoration - elseif filled i : - contour pathpart i - withpen penpart i - decoration - elseif textual i : - also i - decoration - else : - also i - fi - ; - endfor ; - currentpicture -enddef ; - -% path mfun_bleed_box ; - -% primarydef p bleeded d = -% image ( -% mfun_bleed_box := boundingbox p ; -% if pair d : -% draw p xysized (bbwidth(p)+2*xpart d,bbheight(p)+2*ypart d) shifted -d ; -% else : -% draw p xysized (bbwidth(p)+2d,bbheight(p)+2d) shifted (-d,-d) ; -% fi ; -% setbounds currentpicture to mfun_bleed_box ; -% ) -% enddef ; - -%D New helpers: - -def beginglyph(expr unicode, width, height, depth) = - beginfig(unicode) ; % the number is irrelevant - charcode := unicode ; - charwd := width ; - charht := height ; - chardp := depth ; +primarydef p ystretched h = + (p if (bbheight(p)>0) and (h>0) : yscaled (h/bbheight(p)) fi) enddef ; -def endglyph = - setbounds currentpicture to (boundingbox unitsquare xscaled charwd yscaled (charht + chardp) shifted (0,-chardp)) ; - if known charscale : - currentpicture := currentpicture scaled charscale ; - fi ; - endfig ; +primarydef p snapped s = + hide ( if path p : + forever : + exitif (bbheight(p) <= s) and (bbwidth(p) <= s) ; + p := p scaled (1/2) ; + endfor ; + elseif numeric p : + forever : + exitif p <= s ; + p := p scaled (1/2) ; + endfor ; + fi ; ) + p enddef ; -%D Dimensions have bever been an issue as traditional MP can't make that large -%D pictures, but with double mode we need a catch: - -newinternal maxdimensions ; maxdimensions := 14000 ; - -def mfun_apply_max_dimensions = % not a generic helper, we want to protect this one - if bbwidth currentpicture > maxdimensions : - currentpicture := currentpicture if bbheight currentpicture > bbwidth currentpicture : ysized else : xsized fi maxdimensions ; - elseif bbheight currentpicture > maxdimensions : - currentpicture := currentpicture ysized maxdimensions ; - fi ; -enddef; - -extra_endfig := extra_endfig & "mfun_apply_max_dimensions ;" ; - let dump = relax ; diff --git a/metapost/context/base/mp-tool.mpiv b/metapost/context/base/mp-tool.mpiv index 4ca2ea0f9..672a051c2 100644 --- a/metapost/context/base/mp-tool.mpiv +++ b/metapost/context/base/mp-tool.mpiv @@ -289,14 +289,10 @@ vardef set_outer_boundingbox text q = % obsolete setbounds q to outerboundingbox q; enddef; -%D Some missing functions can be implemented rather straightforward (thanks to -%D Taco and others): +%D Some missing functions can be implemented rather +%D straightforward: -pi := 3.14159265358979323846 ; radian := 180/pi ; % 2pi*radian = 360 ; - -% let +++ = ++ ; - -numeric Pi ; Pi := pi ; % for some old compatibility reasons i guess +numeric Pi ; Pi := 3.1415926 ; vardef sqr primary x = x*x enddef ; vardef log primary x = if x=0: 0 else: mlog(x)/mlog(10) fi enddef ; @@ -306,6 +302,15 @@ vardef inv primary x = if x=0: 0 else: x**-1 fi enddef ; vardef pow (expr x,p) = x**p enddef ; +vardef asin primary x = x+(x**3)/6+3(x**5)/40 enddef ; +vardef acos primary x = asin(-x) enddef ; +vardef atan primary x = x-(x**3)/3+(x**5)/5-(x**7)/7 enddef ; +vardef tand primary x = sind(x)/cosd(x) enddef ; + +%D Here are Taco Hoekwater's alternatives (but vardef'd and primaried). + +pi := 3.1415926 ; radian := 180/pi ; % 2pi*radian = 360 ; + vardef tand primary x = sind(x)/cosd(x) enddef ; vardef cotd primary x = cosd(x)/sind(x) enddef ; @@ -316,11 +321,9 @@ vardef cot primary x = cos(x)/sin(x) enddef ; vardef asin primary x = angle((1+-+x,x)) enddef ; vardef acos primary x = angle((x,1+-+x)) enddef ; -vardef atan primary x = angle(1,x) enddef ; vardef invsin primary x = (asin(x))/radian enddef ; vardef invcos primary x = (acos(x))/radian enddef ; -vardef invtan primary x = (atan(x))/radian enddef ; vardef acosh primary x = ln(x+(x+-+1)) enddef ; vardef asinh primary x = ln(x+(x++1)) enddef ; @@ -1220,7 +1223,7 @@ enddef ; extra_endfig := extra_endfig & " naturalizepaths ; " ; -%D Nice tracer: +%D Noce tracer: def drawboundary primary p = draw p dashed evenly withcolor white ; diff --git a/scripts/context/lua/mtx-bibtex.lua b/scripts/context/lua/mtx-bibtex.lua deleted file mode 100644 index c81fd596f..000000000 --- a/scripts/context/lua/mtx-bibtex.lua +++ /dev/null @@ -1,106 +0,0 @@ -if not modules then modules = { } end modules ['mtx-bibtex'] = { - version = 1.002, - comment = "this script is part of publication support", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE", - license = "see context related readme files" -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-bibtex</entry> - <entry name="detail">bibtex helpers</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="toxml"><short>convert bibtex database(s) to xml</short></flag> - <flag name="tolua"><short>convert bibtex database(s) to lua</short></flag> - </subcategory> - </category> - </flags> - <examples> - <category> - <title>Example</title> - <subcategory> - <example><command>mtxrun --script bibtex --tolua bibl-001.bib</command></example> - <example><command>mtxrun --script bibtex --tolua --simple bibl-001.bib</command></example> - <example><command>mtxrun --script bibtex --toxml bibl-001.bib bibl-002.bib bibl-003.bib biblio.xml</command></example> - </subcategory> - </category> - </examples> -</application> -]] - -local application = logs.application { - name = "mtx-bibtex", - banner = "bibtex helpers", - helpinfo = helpinfo, -} - -local report = application.report - -require("publ-dat") - -scripts = scripts or { } -scripts.bibtex = scripts.bibtex or { } - -function scripts.bibtex.toxml(files) - local instance = bibtex.new() - local target = "mtx-bibtex-output.xml" - for i=1,#files do - local filename = files[i] - local filetype = file.suffix(filename) - if filetype == "xml" then - target = filename - elseif filetype == "bib" then - bibtex.load(instance,filename) - else - -- not supported - end - end - bibtex.converttoxml(instance,true) - instance.shortcuts = nil - instance.luadata = nil - xml.save(instance.xmldata,target) -end - -function scripts.bibtex.tolua(files) - local instance = bibtex.new() - local target = "mtx-bibtex-output.lua" - for i=1,#files do - local filename = files[i] - local filetype = file.suffix(filename) - if filetype == "lua" then - target = filename - elseif filetype == "bib" then - bibtex.load(instance,filename) - else - -- not supported - end - end - instance.shortcuts = nil - instance.xmldata = nil - bibtex.analyze(instance) - if environment.arguments.simple then - table.save(target,instance) - else - table.save(target,instance.luadata) - end -end - -if environment.arguments.toxml then - scripts.bibtex.toxml(environment.files) -elseif environment.arguments.tolua then - scripts.bibtex.tolua(environment.files) -elseif environment.arguments.exporthelp then - application.export(environment.arguments.exporthelp,environment.files[1]) -else - application.help() -end - --- scripts.bibtex.toxml { "tugboat.bib" } --- scripts.bibtex.tolua { "tugboat.bib" } diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua index 90efb5225..4c6672051 100644 --- a/scripts/context/lua/mtx-context.lua +++ b/scripts/context/lua/mtx-context.lua @@ -87,17 +87,14 @@ scripts.context = scripts.context or { } -- for the moment here -if jit then -- already luajittex - setargument("engine","luajittex") - setargument("jit",nil) -elseif getargument("jit") or getargument("jiton") then -- relaunch luajittex +if getargument("jit") or getargument("jiton") then -- bonus shortcut, we assume than --jit also indicates the engine -- although --jit and --engine=luajittex are independent setargument("engine","luajittex") end -local engine_new = file.nameonly(getargument("engine") or directives.value("system.engine")) -local engine_old = file.nameonly(environment.ownbin) +local engine_new = getargument("engine") or directives.value("system.engine") +local engine_old = environment.ownbin local function restart(engine_old,engine_new) local command = format("%s --luaonly %q %s --redirected",engine_new,environment.ownname,environment.reconstructcommandline()) @@ -256,9 +253,8 @@ end -- multipass control -local multipass_suffixes = { ".tuc" } -local multipass_nofruns = 8 -- or 7 to test oscillation -local multipass_forcedruns = false +local multipass_suffixes = { ".tuc" } +local multipass_nofruns = 8 -- or 7 to test oscillation local function multipass_hashfiles(jobname) local hash = { } @@ -694,7 +690,6 @@ function scripts.context.run(ctxdata,filename) c_flags.final = false c_flags.kindofrun = (a_once and 3) or (currentrun==1 and 1) or (currentrun==maxnofruns and 4) or 2 c_flags.maxnofruns = maxnofruns - c_flags.forcedruns = multipass_forcedruns and multipass_forcedruns > 0 and multipass_forcedruns or nil c_flags.currentrun = currentrun c_flags.noarrange = a_noarrange or a_arrange or nil -- @@ -712,15 +707,10 @@ function scripts.context.run(ctxdata,filename) break elseif returncode == 0 then multipass_copyluafile(jobname) - if not multipass_forcedruns then - newhash = multipass_hashfiles(jobname) - if multipass_changed(oldhash,newhash) then - oldhash = newhash - else - break - end - elseif currentrun == multipass_forcedruns then - report("quitting after force %i runs",multipass_forcedruns) + newhash = multipass_hashfiles(jobname) + if multipass_changed(oldhash,newhash) then + oldhash = newhash + else break end else @@ -1488,12 +1478,9 @@ do end if getargument("once") then - multipass_nofruns = 1 -else - if getargument("runs") then - multipass_nofruns = tonumber(getargument("runs")) or nil - end - multipass_forcedruns = tonumber(getargument("forcedruns")) or nil + multipass_nofruns = 1 +elseif getargument("runs") then + multipass_nofruns = tonumber(getargument("runs")) or nil end if getargument("run") then diff --git a/scripts/context/lua/mtx-fonts.lua b/scripts/context/lua/mtx-fonts.lua index 675d9fb12..4340cb357 100644 --- a/scripts/context/lua/mtx-fonts.lua +++ b/scripts/context/lua/mtx-fonts.lua @@ -413,12 +413,8 @@ function scripts.fonts.save() local sub = givenfiles[2] or "" local function save(savename,fontblob) if fontblob then - if fontblob.validation_state and table.contains(fontblob.validation_state,"bad_ps_fontname") then - report("ignoring bad fontname for %a",name) - savename = file.nameonly(name) .. "-bad-ps-name" - end savename = file.addsuffix(string.lower(savename),"lua") - report("fontsave, saving data in %a",savename) + report("fontsave, saving data in %s",savename) table.tofile(savename,fontloader.to_table(fontblob),"return") fontloader.close(fontblob) end @@ -430,7 +426,7 @@ function scripts.fonts.save() if suffix == 'ttf' or suffix == 'otf' or suffix == 'ttc' or suffix == "dfont" then local fontinfo = fontloader.info(filename) if fontinfo then - report("font: %a located as %a",name,filename) + report("font: %s located as %s",name,filename) if #fontinfo > 0 then for k=1,#fontinfo do local v = fontinfo[k] @@ -440,13 +436,13 @@ function scripts.fonts.save() save(fontinfo.fullname,fontloader.open(filename)) end else - report("font: %a cannot be read",filename) + report("font: %s cannot be read",filename) end else - report("font: %a not saved",filename) + report("font: %s not saved",filename) end else - report("font: %a not found",name) + report("font: %s not found",name) end else report("font: no name given") diff --git a/scripts/context/lua/mtx-plain.lua b/scripts/context/lua/mtx-plain.lua index de13717d3..d10c21375 100644 --- a/scripts/context/lua/mtx-plain.lua +++ b/scripts/context/lua/mtx-plain.lua @@ -114,7 +114,7 @@ local texformat = environment.arguments.texformat or environment.arguments.forma local texengine = environment.arguments.texengine or environment.arguments.engine if type(texengine) ~= "string" or texengine == "" then - texengine = (jit or environment.arguments.jit) and "luajittex" or "luatex" + texengine = environment.arguments.jit and "luajittex" or"luatex" end if type(texformat) ~= "string" or texformat == "" then diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua index 3372831b3..0ff2d2897 100644 --- a/scripts/context/lua/mtxrun.lua +++ b/scripts/context/lua/mtxrun.lua @@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lua"] = package.loaded["l-lua"] or true --- original size: 3247, stripped down to: 1763 +-- original size: 3123, stripped down to: 1694 if not modules then modules={} end modules ['l-lua']={ version=1.001, @@ -136,9 +136,6 @@ function optionalrequire(...) return result end end -if lua then - lua.mask=load([[τεχ = 1]]) and "utf" or "ascii" -end end -- of closure @@ -437,7 +434,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 29808, stripped down to: 16182 +-- original size: 29245, stripped down to: 15964 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -453,9 +450,7 @@ local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.forma local floor=math.floor local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print -if setinspector then - setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) -end +setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) lpeg.patterns=lpeg.patterns or {} local patterns=lpeg.patterns local anything=P(1) @@ -524,11 +519,9 @@ patterns.spacer=spacer patterns.whitespace=whitespace patterns.nonspacer=nonspacer patterns.nonwhitespace=nonwhitespace -local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) -local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0) +local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0)) patterns.stripper=stripper -patterns.fullstripper=fullstripper patterns.collapser=collapser patterns.lowercase=lowercase patterns.uppercase=uppercase @@ -751,7 +744,7 @@ function lpeg.replacer(one,two,makefunction,isutf) return pattern end end -function lpeg.finder(lst,makefunction,isutf) +function lpeg.finder(lst,makefunction) local pattern if type(lst)=="table" then pattern=P(false) @@ -767,11 +760,7 @@ function lpeg.finder(lst,makefunction,isutf) else pattern=P(lst) end - if isutf then - pattern=((utf8char or 1)-pattern)^0*pattern - else - pattern=(1-pattern)^0*pattern - end + pattern=(1-pattern)^0*pattern if makefunction then return function(str) return lpegmatch(pattern,str) @@ -1082,7 +1071,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-string"] = package.loaded["l-string"] or true --- original size: 5671, stripped down to: 2827 +-- original size: 5547, stripped down to: 2708 if not modules then modules={} end modules ['l-string']={ version=1.001, @@ -1118,15 +1107,11 @@ function string.limit(str,n,sentinel) end end local stripper=patterns.stripper -local fullstripper=patterns.fullstripper local collapser=patterns.collapser local longtostring=patterns.longtostring function string.strip(str) return lpegmatch(stripper,str) or "" end -function string.fullstrip(str) - return lpegmatch(fullstripper,str) or "" -end function string.collapsespaces(str) return lpegmatch(collapser,str) or "" end @@ -1187,7 +1172,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 31142, stripped down to: 20283 +-- original size: 31113, stripped down to: 20256 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -2015,9 +2000,7 @@ function table.print(t,...) serialize(print,t,...) end end -if setinspector then - setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) -end +setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) function table.sub(t,i,j) return { unpack(t,i,j) } end @@ -3524,7 +3507,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-url"] = package.loaded["l-url"] or true --- original size: 12292, stripped down to: 5585 +-- original size: 11993, stripped down to: 5584 if not modules then modules={} end modules ['l-url']={ version=1.001, @@ -3551,7 +3534,7 @@ local hexdigit=R("09","AF","af") local plus=P("+") local nothing=Cc("") local escapedchar=(percent*C(hexdigit*hexdigit))/tochar -local escaped=(plus/" ")+escapedchar +local escaped=(plus/" ")+escapedchar local noslash=P("/")/"" local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2) local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0) @@ -3735,7 +3718,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-dir"] = package.loaded["l-dir"] or true --- original size: 14768, stripped down to: 9107 +-- original size: 14229, stripped down to: 8740 if not modules then modules={} end modules ['l-dir']={ version=1.001, @@ -3758,7 +3741,6 @@ local isdir=lfs.isdir local isfile=lfs.isfile local currentdir=lfs.currentdir local chdir=lfs.chdir -local mkdir=lfs.mkdir local onwindows=os.type=="windows" or find(os.getenv("PATH"),";") if not isdir then function isdir(name) @@ -3931,27 +3913,16 @@ end local make_indeed=true if onwindows then function dir.mkdirs(...) - local n=select("#",...) - local str - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - local s=select(i,...) - if s=="" then - elseif str=="" then - str=s - else - str=str.."/"..s - end + local str,pth="","" + for i=1,select("#",...) do + local s=select(i,...) + if s=="" then + elseif str=="" then + str=s + else + str=str.."/"..s end end - local pth="" local drive=false local first,middle,last=match(str,"^(//)(//*)(.*)$") if first then @@ -3986,30 +3957,21 @@ if onwindows then pth=pth.."/"..s end if make_indeed and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end return pth,(isdir(pth)==true) end else function dir.mkdirs(...) - local n=select("#",...) - local str,pth - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - if s and s~="" then - if str~="" then - str=str.."/"..s - else - str=s - end + local str,pth="","" + for i=1,select("#",...) do + local s=select(i,...) + if s and s~="" then + if str~="" then + str=str.."/"..s + else + str=s end end end @@ -4024,7 +3986,7 @@ else pth=pth.."/"..s end if make_indeed and not first and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end else @@ -4032,7 +3994,7 @@ else for s in gmatch(str,"[^/]+") do pth=pth.."/"..s if make_indeed and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end end @@ -4840,7 +4802,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 29502, stripped down to: 16632 +-- original size: 26857, stripped down to: 15062 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -4859,19 +4821,8 @@ local unpack,concat=table.unpack,table.concat local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc local patterns,lpegmatch=lpeg.patterns,lpeg.match local utfchar,utfbyte=utf.char,utf.byte -local loadstripped=nil -if _LUAVERSION<5.2 then - loadstripped=function(str,shortcuts) - return load(str) - end -else - loadstripped=function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end +local loadstripped=_LUAVERSION<5.2 and load or function(str) + return load(dump(load(str),true)) end if not number then number={} end local stripper=patterns.stripzeros @@ -5021,58 +4972,31 @@ function number.sparseexponent(f,n) end return tostring(n) end +local preamble=[[ +local type = type +local tostring = tostring +local tonumber = tonumber +local format = string.format +local concat = table.concat +local signed = number.signed +local points = number.points +local basepoints = number.basepoints +local utfchar = utf.char +local utfbyte = utf.byte +local lpegmatch = lpeg.match +local nspaces = string.nspaces +local tracedchar = string.tracedchar +local autosingle = string.autosingle +local autodouble = string.autodouble +local sequenced = table.sequenced +local formattednumber = number.formatted +local sparseexponent = number.sparseexponent +]] local template=[[ %s %s return function(%s) return %s end ]] -local preamble,environment="",{} -if _LUAVERSION<5.2 then - preamble=[[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] -else - environment={ - global=global or _G, - lpeg=lpeg, - type=type, - tostring=tostring, - tonumber=tonumber, - format=string.format, - concat=table.concat, - signed=number.signed, - points=number.points, - basepoints=number.basepoints, - utfchar=utf.char, - utfbyte=utf.byte, - lpegmatch=lpeg.match, - nspaces=string.nspaces, - tracedchar=string.tracedchar, - autosingle=string.autosingle, - autodouble=string.autodouble, - sequenced=table.sequenced, - formattednumber=number.formatted, - sparseexponent=number.sparseexponent, - } -end local arguments={ "a1" } setmetatable(arguments,{ __index=function(t,k) local v=t[k-1]..",a"..k @@ -5394,8 +5318,8 @@ local builder=Cs { "start", ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension, } local direct=Cs ( - P("%")*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*P(-1)/[[local format = string.format return function(str) return format("%0",str) end]] -) + P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1) + ) local function make(t,str) local f local p @@ -5407,7 +5331,7 @@ local function make(t,str) p=lpegmatch(builder,str,1,"..",t._extensions_) if n>0 then p=format(template,preamble,t._preamble_,arguments[n],p) - f=loadstripped(p,t._environment_)() + f=loadstripped(p)() else f=function() return str end end @@ -5419,22 +5343,10 @@ local function use(t,fmt,...) return t[fmt](...) end strings.formatters={} -if _LUAVERSION<5.2 then - function strings.formatters.new() - local t={ _extensions_={},_preamble_=preamble,_environment_={},_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end -else - function strings.formatters.new() - local e={} - for k,v in next,environment do - e[k]=v - end - local t={ _extensions_={},_preamble_="",_environment_=e,_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end +function strings.formatters.new() + local t={ _extensions_={},_preamble_="",_type_="formatter" } + setmetatable(t,{ __index=make,__call=use }) + return t end local formatters=strings.formatters.new() string.formatters=formatters @@ -5442,12 +5354,8 @@ string.formatter=function(str,...) return formatters[str](...) end local function add(t,name,template,preamble) if type(t)=="table" and t._type_=="formatter" then t._extensions_[name]=template or "%s" - if type(preamble)=="string" then + if preamble then t._preamble_=preamble.."\n"..t._preamble_ - elseif type(preamble)=="table" then - for k,v in next,preamble do - t._environment_[k]=v - end end end end @@ -5456,15 +5364,9 @@ patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"" patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) -if _LUAVERSION<5.2 then - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") -else - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape }) -end +add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) +add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) +add(formatters,"lua",[[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) end -- of closure @@ -5473,7 +5375,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 23980, stripped down to: 16119 +-- original size: 23952, stripped down to: 16092 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -5708,7 +5610,7 @@ local f_ordered_string=formatters["%q,"] local f_ordered_number=formatters["%s,"] local f_ordered_boolean=formatters["%l,"] function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } + local r={ prefix or "return" } local m=1 local function fastserialize(t,outer) local n=#t @@ -7747,7 +7649,7 @@ do -- create closure to overcome 200 locals limit package.loaded["trac-inf"] = package.loaded["trac-inf"] or true --- original size: 6643, stripped down to: 5272 +-- original size: 6501, stripped down to: 5156 if not modules then modules={} end modules ['trac-inf']={ version=1.001, @@ -7848,10 +7750,7 @@ function statistics.show() if statistics.enable then local register=statistics.register register("used platform",function() - local mask=lua.mask or "ascii" - return format("%s, type: %s, binary subtree: %s, symbol mask: %s (%s)", - os.platform or "unknown",os.type or "unknown",environment.texos or "unknown", - mask,mask=="utf" and "τεχ" or "tex") + return format("%s, type: %s, binary subtree: %s",os.platform or "unknown",os.type or "unknown",environment.texos or "unknown") end) register("luatex banner",function() return lower(status.banner) @@ -7930,7 +7829,7 @@ do -- create closure to overcome 200 locals limit package.loaded["trac-pro"] = package.loaded["trac-pro"] or true --- original size: 5829, stripped down to: 3501 +-- original size: 5773, stripped down to: 3453 if not modules then modules={} end modules ['trac-pro']={ version=1.001, @@ -7947,16 +7846,14 @@ local namespaces=namespaces local registered={} local function report_index(k,name) if trace_namespaces then - report_system("reference to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) + report_system("reference to %a in protected namespace %a: %s",k,name,debug.traceback()) else report_system("reference to %a in protected namespace %a",k,name) end end local function report_newindex(k,name) if trace_namespaces then - report_system("assignment to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) + report_system("assignment to %a in protected namespace %a: %s",k,name,debug.traceback()) else report_system("assignment to %a in protected namespace %a",k,name) end @@ -8207,7 +8104,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-deb"] = package.loaded["util-deb"] or true --- original size: 3898, stripped down to: 2644 +-- original size: 3708, stripped down to: 2568 if not modules then modules={} end modules ['util-deb']={ version=1.001, @@ -8287,22 +8184,20 @@ end function debugger.disable() debug.sethook() end -local function showtraceback(rep) - local level=2 - local reporter=rep or report +function traceback() + local level=1 while true do - local info=getinfo(level,"Sl") + local info=debug.getinfo(level,"Sl") if not info then break elseif info.what=="C" then - reporter("%2i : %s",level-1,"C function") + print(format("%3i : C function",level)) else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) + print(format("%3i : [%s]:%d",level,info.short_src,info.currentline)) end level=level+1 end end -debugger.showtraceback=showtraceback end -- of closure @@ -8968,7 +8863,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true --- original size: 42614, stripped down to: 26694 +-- original size: 42447, stripped down to: 26589 if not modules then modules={} end modules ['lxml-tab']={ version=1.001, @@ -9494,11 +9389,8 @@ local function _xmlconvert_(data,settings) end if errorstr and errorstr~="" then result.error=true - else - errorstr=nil end result.statistics={ - errormessage=errorstr, entities={ decimals=dcache, hexadecimals=hcache, @@ -9696,26 +9588,24 @@ local function verbose_document(e,handlers) end end local function serialize(e,handlers,...) - if e then - local initialize=handlers.initialize - local finalize=handlers.finalize - local functions=handlers.functions - if initialize then - local state=initialize(...) - if not state==true then - return state - end - end - local etg=e.tg - if etg then - (functions[etg] or functions["@el@"])(e,handlers) - else - functions["@dc@"](e,handlers) - end - if finalize then - return finalize() + local initialize=handlers.initialize + local finalize=handlers.finalize + local functions=handlers.functions + if initialize then + local state=initialize(...) + if not state==true then + return state end end + local etg=e.tg + if etg then + (functions[etg] or functions["@el@"])(e,handlers) + else + functions["@dc@"](e,handlers) + end + if finalize then + return finalize() + end end local function xserialize(e,handlers) local functions=handlers.functions @@ -15485,7 +15375,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-use"] = package.loaded["data-use"] or true --- original size: 3899, stripped down to: 2984 +-- original size: 3913, stripped down to: 2998 if not modules then modules={} end modules ['data-use']={ version=1.001, @@ -15531,7 +15421,7 @@ end statistics.register("used config file",function() return caches.configfiles() end) statistics.register("used cache path",function() return caches.usedpaths() end) function statistics.savefmtstatus(texname,formatbanner,sourcefile) - local enginebanner=status.banner + local enginebanner=status.list().banner if formatbanner and enginebanner and sourcefile then local luvname=file.replacesuffix(texname,"luv") local luvdata={ @@ -15544,7 +15434,7 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile) end end function statistics.checkfmtstatus(texname) - local enginebanner=status.banner + local enginebanner=status.list().banner if enginebanner and texname then local luvname=file.replacesuffix(texname,"luv") if lfs.isfile(luvname) then @@ -16168,7 +16058,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-aux"] = package.loaded["data-aux"] or true --- original size: 2431, stripped down to: 1996 +-- original size: 2394, stripped down to: 2005 if not modules then modules={} end modules ['data-aux']={ version=1.001, @@ -16182,8 +16072,8 @@ local type,next=type,next local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) local resolvers=resolvers local report_scripts=logs.reporter("resolvers","scripts") -function resolvers.updatescript(oldname,newname) - local scriptpath="context/lua" +function resolvers.updatescript(oldname,newname) + local scriptpath="scripts/context/lua" newname=file.addsuffix(newname,"lua") local oldscript=resolvers.cleanpath(oldname) if trace_locating then @@ -16791,8 +16681,8 @@ end -- of closure -- used libraries : l-lua.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 689993 --- stripped bytes : 244562 +-- original bytes : 685064 +-- stripped bytes : 242353 -- end library merge @@ -16891,18 +16781,17 @@ local ownlibs = { -- order can be made better } --- c:/data/develop/tex-context/tex/texmf-win64/bin/../../texmf-context/tex/context/base/data-tmf.lua --- c:/data/develop/context/sources/data-tmf.lua - local ownlist = { - -- '.', - -- ownpath , - owntree .. "/../../../../context/sources", -- HH's development path + '.', + ownpath , + ownpath .. "/../sources", -- HH's development path owntree .. "/../../texmf-local/tex/context/base", owntree .. "/../../texmf-context/tex/context/base", + owntree .. "/../../texmf-dist/tex/context/base", owntree .. "/../../texmf/tex/context/base", owntree .. "/../../../texmf-local/tex/context/base", owntree .. "/../../../texmf-context/tex/context/base", + owntree .. "/../../../texmf-dist/tex/context/base", owntree .. "/../../../texmf/tex/context/base", } @@ -17809,12 +17698,6 @@ if e_argument("ansi") then status_nop = formatters["[1;32m%-15s [0;1m:[0m\n"], } - local script = e_argument("script") or e_argument("scripts") - - if type(script) == "string" then - logs.writer("]0;"..script.."") -- for Alan to test - end - end if e_argument("script") or e_argument("scripts") then @@ -17838,16 +17721,8 @@ elseif e_argument("selfmerge") then runners.loadbase() local found = locate_libs() - if found then - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfmerge(mtxrun,own.libs,{ found }) - application.report("runner updated on resolved path: %s",mtxrun) - else - utilities.merger.selfmerge(own.name,own.libs,{ found }) - application.report("runner updated on relative path: %s",own.name) - end + utilities.merger.selfmerge(own.name,own.libs,{ found }) end elseif e_argument("selfclean") then @@ -17855,15 +17730,7 @@ elseif e_argument("selfclean") then -- remove embedded libraries runners.loadbase() - - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfclean(mtxrun) - application.report("runner cleaned on resolved path: %s",mtxrun) - else - utilities.merger.selfclean(own.name) - application.report("runner cleaned on relative path: %s",own.name) - end + utilities.merger.selfclean(own.name) elseif e_argument("selfupdate") then @@ -18105,8 +17972,6 @@ elseif e_argument("version") then application.version() - application.report("source path",environment.ownbin) - elseif e_argument("directives") then directives.show() diff --git a/scripts/context/stubs/install/first-setup.sh b/scripts/context/stubs/install/first-setup.sh deleted file mode 100644 index 9249fd2e0..000000000 --- a/scripts/context/stubs/install/first-setup.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/sh - -# Takes the same arguments as mtx-update - -# you may change this if you want ... -CONTEXTROOT="$PWD/tex" - -# suggested by Tobias Florek to check for ruby & rsync -if [ ! -x "`which rsync`" ]; then - echo "You need to install rsync first." - exit 1 -fi -if [ ! -x "`which ruby`" ]; then - echo "You might want to install Ruby first if you want to use pdfTeX or XeTeX." -fi - -system=`uname -s` -cpu=`uname -m` - -case "$system" in - # linux - Linux) - case "$cpu" in - i*86) platform="linux" ;; - x86_64|ia64) platform="linux-64" ;; - # a little bit of cheating with ppc64 (won't work on Gentoo) - ppc|ppc64) platform="linux-ppc" ;; - # we currently support just mipsel, but Debian is lying (reports mips64) - # we need more hacks to fix the situation, this is just a temporary solution - mips|mips64|mipsel|mips64el) platform="linux-mipsel" ;; - *) platform="unknown" ;; - esac ;; - # Mac OS X - Darwin) - case "$cpu" in - i*86) platform="osx-intel" ;; - x86_64) platform="osx-64" ;; - ppc*|powerpc|power*|Power*) platform="osx-ppc" ;; - *) platform="unknown" ;; - esac ;; - # FreeBSD - FreeBSD|freebsd) - case "$cpu" in - i*86) platform="freebsd" ;; - x86_64) platform="freebsd" ;; # no special binaries are available yet - amd64) platform="freebsd-amd64" ;; - *) platform="unknown" ;; - esac ;; - # kFreeBSD (debian) - GNU/kFreeBSD) - case "$cpu" in - i*86) platform="kfreebsd-i386" ;; - x86_64|amd64) platform="kfreebsd-amd64" ;; - *) platform="unknown" ;; - esac ;; - # cygwin - CYGWIN*) - case "$cpu" in - i*86) platform="cygwin" ;; - x86_64|ia64) platform="cygwin-64" ;; - *) platform="unknown" ;; - esac ;; - # SunOS/Solaris - SunOS) - case "$cpu" in - sparc) platform="solaris-sparc" ;; - i86pc) platform="solaris-intel" ;; - *) platform="unknown" ;; - esac ;; - *) platform="unknown" -esac - -# temporary patch for 64-bit Leopard with 32-bit kernel -if test "$platform" = "osx-intel"; then - # if running Snow Leopard or later - # better: /usr/bin/sw_vers -productVersion - if test `uname -r|cut -f1 -d"."` -ge 10 ; then - # if working on 64-bit hardware - if test `sysctl -n hw.cpu64bit_capable` = 1; then - # snowleopard32=TRUE - platform="osx-64" - fi - fi -fi - -if test "$platform" = "unknown" ; then - echo "Error: your system \"$system $cpu\" is not supported yet." - echo "Please report to the ConTeXt mailing-list (ntg-context@ntg.nl)" - exit -fi - -# if you want to enforce some specific platform -# (when 'uname' doesn't agree with true architecture), uncomment and modify next line: -# platform=linux - -# download or rsync the latest scripts first -rsync -rlptv rsync://contextgarden.net/minimals/setup/$platform/bin . - -# download or update the distribution -# you may remove the --context=beta switch if you want to use "current" -# you can use --engine=luatex if you want just mkiv -env PATH="$PWD/bin:$CONTEXTROOT/texmf-$platform/bin:$PATH" \ -mtxrun --script ./bin/mtx-update.lua --force --update --make --context=beta --platform=$platform --texroot="$CONTEXTROOT" $@ - -echo -echo "When you want to use context, you need to initialize the tree by typing:" -echo -echo " . $CONTEXTROOT/setuptex" -echo -echo "in your shell or add" -echo " \"$CONTEXTROOT/texmf-$platform/bin\"" -echo "to PATH variable if you want to set it permanently." -echo "This can usually be done in .bashrc, .bash_profile" -echo "(or whatever file is used to initialize your shell)." -echo - -if [ ! -x "`which ruby`" ]; then - echo "You might want to install Ruby first if you want to use pdfTeX or XeTeX." - echo -fi diff --git a/scripts/context/stubs/mswin/context.exe b/scripts/context/stubs/mswin/context.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/context.exe +++ b/scripts/context/stubs/mswin/context.exe diff --git a/scripts/context/stubs/mswin/ctxtools.exe b/scripts/context/stubs/mswin/ctxtools.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/ctxtools.exe +++ b/scripts/context/stubs/mswin/ctxtools.exe diff --git a/scripts/context/stubs/install/first-setup.bat b/scripts/context/stubs/mswin/first-setup.bat index f06ad0e6b..f06ad0e6b 100644 --- a/scripts/context/stubs/install/first-setup.bat +++ b/scripts/context/stubs/mswin/first-setup.bat diff --git a/scripts/context/stubs/mswin/luatools.exe b/scripts/context/stubs/mswin/luatools.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/luatools.exe +++ b/scripts/context/stubs/mswin/luatools.exe diff --git a/scripts/context/stubs/mswin/metatex.exe b/scripts/context/stubs/mswin/metatex.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/metatex.exe +++ b/scripts/context/stubs/mswin/metatex.exe diff --git a/scripts/context/stubs/mswin/mptopdf.exe b/scripts/context/stubs/mswin/mptopdf.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/mptopdf.exe +++ b/scripts/context/stubs/mswin/mptopdf.exe diff --git a/scripts/context/stubs/mswin/mtxrun.dll b/scripts/context/stubs/mswin/mtxrun.dll Binary files differindex 3c4481c31..5a79e1bad 100644 --- a/scripts/context/stubs/mswin/mtxrun.dll +++ b/scripts/context/stubs/mswin/mtxrun.dll diff --git a/scripts/context/stubs/mswin/mtxrun.exe b/scripts/context/stubs/mswin/mtxrun.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/mtxrun.exe +++ b/scripts/context/stubs/mswin/mtxrun.exe diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua index 3372831b3..0ff2d2897 100644 --- a/scripts/context/stubs/mswin/mtxrun.lua +++ b/scripts/context/stubs/mswin/mtxrun.lua @@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lua"] = package.loaded["l-lua"] or true --- original size: 3247, stripped down to: 1763 +-- original size: 3123, stripped down to: 1694 if not modules then modules={} end modules ['l-lua']={ version=1.001, @@ -136,9 +136,6 @@ function optionalrequire(...) return result end end -if lua then - lua.mask=load([[τεχ = 1]]) and "utf" or "ascii" -end end -- of closure @@ -437,7 +434,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 29808, stripped down to: 16182 +-- original size: 29245, stripped down to: 15964 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -453,9 +450,7 @@ local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.forma local floor=math.floor local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print -if setinspector then - setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) -end +setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) lpeg.patterns=lpeg.patterns or {} local patterns=lpeg.patterns local anything=P(1) @@ -524,11 +519,9 @@ patterns.spacer=spacer patterns.whitespace=whitespace patterns.nonspacer=nonspacer patterns.nonwhitespace=nonwhitespace -local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) -local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0) +local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0)) patterns.stripper=stripper -patterns.fullstripper=fullstripper patterns.collapser=collapser patterns.lowercase=lowercase patterns.uppercase=uppercase @@ -751,7 +744,7 @@ function lpeg.replacer(one,two,makefunction,isutf) return pattern end end -function lpeg.finder(lst,makefunction,isutf) +function lpeg.finder(lst,makefunction) local pattern if type(lst)=="table" then pattern=P(false) @@ -767,11 +760,7 @@ function lpeg.finder(lst,makefunction,isutf) else pattern=P(lst) end - if isutf then - pattern=((utf8char or 1)-pattern)^0*pattern - else - pattern=(1-pattern)^0*pattern - end + pattern=(1-pattern)^0*pattern if makefunction then return function(str) return lpegmatch(pattern,str) @@ -1082,7 +1071,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-string"] = package.loaded["l-string"] or true --- original size: 5671, stripped down to: 2827 +-- original size: 5547, stripped down to: 2708 if not modules then modules={} end modules ['l-string']={ version=1.001, @@ -1118,15 +1107,11 @@ function string.limit(str,n,sentinel) end end local stripper=patterns.stripper -local fullstripper=patterns.fullstripper local collapser=patterns.collapser local longtostring=patterns.longtostring function string.strip(str) return lpegmatch(stripper,str) or "" end -function string.fullstrip(str) - return lpegmatch(fullstripper,str) or "" -end function string.collapsespaces(str) return lpegmatch(collapser,str) or "" end @@ -1187,7 +1172,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 31142, stripped down to: 20283 +-- original size: 31113, stripped down to: 20256 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -2015,9 +2000,7 @@ function table.print(t,...) serialize(print,t,...) end end -if setinspector then - setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) -end +setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) function table.sub(t,i,j) return { unpack(t,i,j) } end @@ -3524,7 +3507,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-url"] = package.loaded["l-url"] or true --- original size: 12292, stripped down to: 5585 +-- original size: 11993, stripped down to: 5584 if not modules then modules={} end modules ['l-url']={ version=1.001, @@ -3551,7 +3534,7 @@ local hexdigit=R("09","AF","af") local plus=P("+") local nothing=Cc("") local escapedchar=(percent*C(hexdigit*hexdigit))/tochar -local escaped=(plus/" ")+escapedchar +local escaped=(plus/" ")+escapedchar local noslash=P("/")/"" local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2) local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0) @@ -3735,7 +3718,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-dir"] = package.loaded["l-dir"] or true --- original size: 14768, stripped down to: 9107 +-- original size: 14229, stripped down to: 8740 if not modules then modules={} end modules ['l-dir']={ version=1.001, @@ -3758,7 +3741,6 @@ local isdir=lfs.isdir local isfile=lfs.isfile local currentdir=lfs.currentdir local chdir=lfs.chdir -local mkdir=lfs.mkdir local onwindows=os.type=="windows" or find(os.getenv("PATH"),";") if not isdir then function isdir(name) @@ -3931,27 +3913,16 @@ end local make_indeed=true if onwindows then function dir.mkdirs(...) - local n=select("#",...) - local str - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - local s=select(i,...) - if s=="" then - elseif str=="" then - str=s - else - str=str.."/"..s - end + local str,pth="","" + for i=1,select("#",...) do + local s=select(i,...) + if s=="" then + elseif str=="" then + str=s + else + str=str.."/"..s end end - local pth="" local drive=false local first,middle,last=match(str,"^(//)(//*)(.*)$") if first then @@ -3986,30 +3957,21 @@ if onwindows then pth=pth.."/"..s end if make_indeed and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end return pth,(isdir(pth)==true) end else function dir.mkdirs(...) - local n=select("#",...) - local str,pth - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - if s and s~="" then - if str~="" then - str=str.."/"..s - else - str=s - end + local str,pth="","" + for i=1,select("#",...) do + local s=select(i,...) + if s and s~="" then + if str~="" then + str=str.."/"..s + else + str=s end end end @@ -4024,7 +3986,7 @@ else pth=pth.."/"..s end if make_indeed and not first and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end else @@ -4032,7 +3994,7 @@ else for s in gmatch(str,"[^/]+") do pth=pth.."/"..s if make_indeed and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end end @@ -4840,7 +4802,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 29502, stripped down to: 16632 +-- original size: 26857, stripped down to: 15062 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -4859,19 +4821,8 @@ local unpack,concat=table.unpack,table.concat local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc local patterns,lpegmatch=lpeg.patterns,lpeg.match local utfchar,utfbyte=utf.char,utf.byte -local loadstripped=nil -if _LUAVERSION<5.2 then - loadstripped=function(str,shortcuts) - return load(str) - end -else - loadstripped=function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end +local loadstripped=_LUAVERSION<5.2 and load or function(str) + return load(dump(load(str),true)) end if not number then number={} end local stripper=patterns.stripzeros @@ -5021,58 +4972,31 @@ function number.sparseexponent(f,n) end return tostring(n) end +local preamble=[[ +local type = type +local tostring = tostring +local tonumber = tonumber +local format = string.format +local concat = table.concat +local signed = number.signed +local points = number.points +local basepoints = number.basepoints +local utfchar = utf.char +local utfbyte = utf.byte +local lpegmatch = lpeg.match +local nspaces = string.nspaces +local tracedchar = string.tracedchar +local autosingle = string.autosingle +local autodouble = string.autodouble +local sequenced = table.sequenced +local formattednumber = number.formatted +local sparseexponent = number.sparseexponent +]] local template=[[ %s %s return function(%s) return %s end ]] -local preamble,environment="",{} -if _LUAVERSION<5.2 then - preamble=[[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] -else - environment={ - global=global or _G, - lpeg=lpeg, - type=type, - tostring=tostring, - tonumber=tonumber, - format=string.format, - concat=table.concat, - signed=number.signed, - points=number.points, - basepoints=number.basepoints, - utfchar=utf.char, - utfbyte=utf.byte, - lpegmatch=lpeg.match, - nspaces=string.nspaces, - tracedchar=string.tracedchar, - autosingle=string.autosingle, - autodouble=string.autodouble, - sequenced=table.sequenced, - formattednumber=number.formatted, - sparseexponent=number.sparseexponent, - } -end local arguments={ "a1" } setmetatable(arguments,{ __index=function(t,k) local v=t[k-1]..",a"..k @@ -5394,8 +5318,8 @@ local builder=Cs { "start", ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension, } local direct=Cs ( - P("%")*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*P(-1)/[[local format = string.format return function(str) return format("%0",str) end]] -) + P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1) + ) local function make(t,str) local f local p @@ -5407,7 +5331,7 @@ local function make(t,str) p=lpegmatch(builder,str,1,"..",t._extensions_) if n>0 then p=format(template,preamble,t._preamble_,arguments[n],p) - f=loadstripped(p,t._environment_)() + f=loadstripped(p)() else f=function() return str end end @@ -5419,22 +5343,10 @@ local function use(t,fmt,...) return t[fmt](...) end strings.formatters={} -if _LUAVERSION<5.2 then - function strings.formatters.new() - local t={ _extensions_={},_preamble_=preamble,_environment_={},_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end -else - function strings.formatters.new() - local e={} - for k,v in next,environment do - e[k]=v - end - local t={ _extensions_={},_preamble_="",_environment_=e,_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end +function strings.formatters.new() + local t={ _extensions_={},_preamble_="",_type_="formatter" } + setmetatable(t,{ __index=make,__call=use }) + return t end local formatters=strings.formatters.new() string.formatters=formatters @@ -5442,12 +5354,8 @@ string.formatter=function(str,...) return formatters[str](...) end local function add(t,name,template,preamble) if type(t)=="table" and t._type_=="formatter" then t._extensions_[name]=template or "%s" - if type(preamble)=="string" then + if preamble then t._preamble_=preamble.."\n"..t._preamble_ - elseif type(preamble)=="table" then - for k,v in next,preamble do - t._environment_[k]=v - end end end end @@ -5456,15 +5364,9 @@ patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"" patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) -if _LUAVERSION<5.2 then - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") -else - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape }) -end +add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) +add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) +add(formatters,"lua",[[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) end -- of closure @@ -5473,7 +5375,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 23980, stripped down to: 16119 +-- original size: 23952, stripped down to: 16092 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -5708,7 +5610,7 @@ local f_ordered_string=formatters["%q,"] local f_ordered_number=formatters["%s,"] local f_ordered_boolean=formatters["%l,"] function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } + local r={ prefix or "return" } local m=1 local function fastserialize(t,outer) local n=#t @@ -7747,7 +7649,7 @@ do -- create closure to overcome 200 locals limit package.loaded["trac-inf"] = package.loaded["trac-inf"] or true --- original size: 6643, stripped down to: 5272 +-- original size: 6501, stripped down to: 5156 if not modules then modules={} end modules ['trac-inf']={ version=1.001, @@ -7848,10 +7750,7 @@ function statistics.show() if statistics.enable then local register=statistics.register register("used platform",function() - local mask=lua.mask or "ascii" - return format("%s, type: %s, binary subtree: %s, symbol mask: %s (%s)", - os.platform or "unknown",os.type or "unknown",environment.texos or "unknown", - mask,mask=="utf" and "τεχ" or "tex") + return format("%s, type: %s, binary subtree: %s",os.platform or "unknown",os.type or "unknown",environment.texos or "unknown") end) register("luatex banner",function() return lower(status.banner) @@ -7930,7 +7829,7 @@ do -- create closure to overcome 200 locals limit package.loaded["trac-pro"] = package.loaded["trac-pro"] or true --- original size: 5829, stripped down to: 3501 +-- original size: 5773, stripped down to: 3453 if not modules then modules={} end modules ['trac-pro']={ version=1.001, @@ -7947,16 +7846,14 @@ local namespaces=namespaces local registered={} local function report_index(k,name) if trace_namespaces then - report_system("reference to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) + report_system("reference to %a in protected namespace %a: %s",k,name,debug.traceback()) else report_system("reference to %a in protected namespace %a",k,name) end end local function report_newindex(k,name) if trace_namespaces then - report_system("assignment to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) + report_system("assignment to %a in protected namespace %a: %s",k,name,debug.traceback()) else report_system("assignment to %a in protected namespace %a",k,name) end @@ -8207,7 +8104,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-deb"] = package.loaded["util-deb"] or true --- original size: 3898, stripped down to: 2644 +-- original size: 3708, stripped down to: 2568 if not modules then modules={} end modules ['util-deb']={ version=1.001, @@ -8287,22 +8184,20 @@ end function debugger.disable() debug.sethook() end -local function showtraceback(rep) - local level=2 - local reporter=rep or report +function traceback() + local level=1 while true do - local info=getinfo(level,"Sl") + local info=debug.getinfo(level,"Sl") if not info then break elseif info.what=="C" then - reporter("%2i : %s",level-1,"C function") + print(format("%3i : C function",level)) else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) + print(format("%3i : [%s]:%d",level,info.short_src,info.currentline)) end level=level+1 end end -debugger.showtraceback=showtraceback end -- of closure @@ -8968,7 +8863,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true --- original size: 42614, stripped down to: 26694 +-- original size: 42447, stripped down to: 26589 if not modules then modules={} end modules ['lxml-tab']={ version=1.001, @@ -9494,11 +9389,8 @@ local function _xmlconvert_(data,settings) end if errorstr and errorstr~="" then result.error=true - else - errorstr=nil end result.statistics={ - errormessage=errorstr, entities={ decimals=dcache, hexadecimals=hcache, @@ -9696,26 +9588,24 @@ local function verbose_document(e,handlers) end end local function serialize(e,handlers,...) - if e then - local initialize=handlers.initialize - local finalize=handlers.finalize - local functions=handlers.functions - if initialize then - local state=initialize(...) - if not state==true then - return state - end - end - local etg=e.tg - if etg then - (functions[etg] or functions["@el@"])(e,handlers) - else - functions["@dc@"](e,handlers) - end - if finalize then - return finalize() + local initialize=handlers.initialize + local finalize=handlers.finalize + local functions=handlers.functions + if initialize then + local state=initialize(...) + if not state==true then + return state end end + local etg=e.tg + if etg then + (functions[etg] or functions["@el@"])(e,handlers) + else + functions["@dc@"](e,handlers) + end + if finalize then + return finalize() + end end local function xserialize(e,handlers) local functions=handlers.functions @@ -15485,7 +15375,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-use"] = package.loaded["data-use"] or true --- original size: 3899, stripped down to: 2984 +-- original size: 3913, stripped down to: 2998 if not modules then modules={} end modules ['data-use']={ version=1.001, @@ -15531,7 +15421,7 @@ end statistics.register("used config file",function() return caches.configfiles() end) statistics.register("used cache path",function() return caches.usedpaths() end) function statistics.savefmtstatus(texname,formatbanner,sourcefile) - local enginebanner=status.banner + local enginebanner=status.list().banner if formatbanner and enginebanner and sourcefile then local luvname=file.replacesuffix(texname,"luv") local luvdata={ @@ -15544,7 +15434,7 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile) end end function statistics.checkfmtstatus(texname) - local enginebanner=status.banner + local enginebanner=status.list().banner if enginebanner and texname then local luvname=file.replacesuffix(texname,"luv") if lfs.isfile(luvname) then @@ -16168,7 +16058,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-aux"] = package.loaded["data-aux"] or true --- original size: 2431, stripped down to: 1996 +-- original size: 2394, stripped down to: 2005 if not modules then modules={} end modules ['data-aux']={ version=1.001, @@ -16182,8 +16072,8 @@ local type,next=type,next local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) local resolvers=resolvers local report_scripts=logs.reporter("resolvers","scripts") -function resolvers.updatescript(oldname,newname) - local scriptpath="context/lua" +function resolvers.updatescript(oldname,newname) + local scriptpath="scripts/context/lua" newname=file.addsuffix(newname,"lua") local oldscript=resolvers.cleanpath(oldname) if trace_locating then @@ -16791,8 +16681,8 @@ end -- of closure -- used libraries : l-lua.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 689993 --- stripped bytes : 244562 +-- original bytes : 685064 +-- stripped bytes : 242353 -- end library merge @@ -16891,18 +16781,17 @@ local ownlibs = { -- order can be made better } --- c:/data/develop/tex-context/tex/texmf-win64/bin/../../texmf-context/tex/context/base/data-tmf.lua --- c:/data/develop/context/sources/data-tmf.lua - local ownlist = { - -- '.', - -- ownpath , - owntree .. "/../../../../context/sources", -- HH's development path + '.', + ownpath , + ownpath .. "/../sources", -- HH's development path owntree .. "/../../texmf-local/tex/context/base", owntree .. "/../../texmf-context/tex/context/base", + owntree .. "/../../texmf-dist/tex/context/base", owntree .. "/../../texmf/tex/context/base", owntree .. "/../../../texmf-local/tex/context/base", owntree .. "/../../../texmf-context/tex/context/base", + owntree .. "/../../../texmf-dist/tex/context/base", owntree .. "/../../../texmf/tex/context/base", } @@ -17809,12 +17698,6 @@ if e_argument("ansi") then status_nop = formatters["[1;32m%-15s [0;1m:[0m\n"], } - local script = e_argument("script") or e_argument("scripts") - - if type(script) == "string" then - logs.writer("]0;"..script.."") -- for Alan to test - end - end if e_argument("script") or e_argument("scripts") then @@ -17838,16 +17721,8 @@ elseif e_argument("selfmerge") then runners.loadbase() local found = locate_libs() - if found then - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfmerge(mtxrun,own.libs,{ found }) - application.report("runner updated on resolved path: %s",mtxrun) - else - utilities.merger.selfmerge(own.name,own.libs,{ found }) - application.report("runner updated on relative path: %s",own.name) - end + utilities.merger.selfmerge(own.name,own.libs,{ found }) end elseif e_argument("selfclean") then @@ -17855,15 +17730,7 @@ elseif e_argument("selfclean") then -- remove embedded libraries runners.loadbase() - - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfclean(mtxrun) - application.report("runner cleaned on resolved path: %s",mtxrun) - else - utilities.merger.selfclean(own.name) - application.report("runner cleaned on relative path: %s",own.name) - end + utilities.merger.selfclean(own.name) elseif e_argument("selfupdate") then @@ -18105,8 +17972,6 @@ elseif e_argument("version") then application.version() - application.report("source path",environment.ownbin) - elseif e_argument("directives") then directives.show() diff --git a/scripts/context/stubs/mswin/mtxrunjit.exe b/scripts/context/stubs/mswin/mtxrunjit.exe Binary files differdeleted file mode 100644 index 0e7882cf9..000000000 --- a/scripts/context/stubs/mswin/mtxrunjit.exe +++ /dev/null diff --git a/scripts/context/stubs/mswin/mtxworks.exe b/scripts/context/stubs/mswin/mtxworks.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/mtxworks.exe +++ b/scripts/context/stubs/mswin/mtxworks.exe diff --git a/scripts/context/stubs/mswin/pstopdf.exe b/scripts/context/stubs/mswin/pstopdf.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/pstopdf.exe +++ b/scripts/context/stubs/mswin/pstopdf.exe diff --git a/scripts/context/stubs/setup/setuptex.bat b/scripts/context/stubs/mswin/setuptex.bat index b61fd4494..b61fd4494 100644 --- a/scripts/context/stubs/setup/setuptex.bat +++ b/scripts/context/stubs/mswin/setuptex.bat diff --git a/scripts/context/stubs/mswin/texexec.exe b/scripts/context/stubs/mswin/texexec.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/texexec.exe +++ b/scripts/context/stubs/mswin/texexec.exe diff --git a/scripts/context/stubs/mswin/texmfstart.exe b/scripts/context/stubs/mswin/texmfstart.exe Binary files differindex 0e7882cf9..faae5caa7 100644 --- a/scripts/context/stubs/mswin/texmfstart.exe +++ b/scripts/context/stubs/mswin/texmfstart.exe diff --git a/scripts/context/stubs/setup/setuptex b/scripts/context/stubs/setup/setuptex deleted file mode 100644 index d41e36707..000000000 --- a/scripts/context/stubs/setup/setuptex +++ /dev/null @@ -1,167 +0,0 @@ -# Example setup file for ConTeXt distribution -# -# Author: Hans Hagen -# Patches: Arthur R. & Mojca M. -# -# Usage: -# . setuptex [texroot] -# -# On the first run also execute: -# mktexlsr -# texexec --make --alone - -# -# PLATFORM -# - -# we will try to guess the platform first -# (needs to be kept in sync with first-setup.sh and mtxrun) -# if yours is missing, let us know - -system=`uname -s` -cpu=`uname -m` - -case "$system" in - # linux - Linux) - case "$cpu" in - i*86) platform="linux" ;; - x86_64|ia64) platform="linux-64" ;; - # a little bit of cheating with ppc64 (won't work on Gentoo) - ppc|ppc64) platform="linux-ppc" ;; - *) platform="unknown" ;; - esac ;; - # Mac OS X - Darwin) - case "$cpu" in - i*86) platform="osx-intel" ;; - x86_64) platform="osx-64" ;; - ppc*|powerpc|power*|Power*) platform="osx-ppc" ;; - *) platform="unknown" ;; - esac ;; - # FreeBSD - FreeBSD|freebsd) - case "$cpu" in - i*86) platform="freebsd" ;; - x86_64) platform="freebsd" ;; - amd64) platform="freebsd-amd64" ;; - *) platform="unknown" ;; - esac ;; - # kFreeBSD (Debian) - GNU/kFreeBSD) - case "$cpu" in - i*86) platform="kfreebsd-i386" ;; - x86_64|amd64) platform="kfreebsd-amd64" ;; - *) platform="unknown" ;; - esac ;; - # cygwin - CYGWIN) - case "$cpu" in - i*86) platform="cygwin" ;; - x86_64|ia64) platform="cygwin-64" ;; - *) platform="unknown" ;; - esac ;; - # SunOS/Solaris - SunOS) - case "$cpu" in - sparc) platform="solaris-sparc" ;; - i86pc) platform="solaris-intel" ;; - *) platform="unknown" ;; - esac ;; - *) platform="unknown" -esac - -# temporary fix for Snow Leopard -if test "$platform" = "osx-intel"; then - # running Snow Leopard or later - if test `uname -r|cut -f1 -d"."` -ge 10 ; then - # working on 64-bit hardware - if test `sysctl -n hw.cpu64bit_capable` = 1; then - platform="osx-64" - fi - fi -fi - -if test "$platform" = "unknown" ; then - echo "Error: your system \"$system $cpu\" is not supported yet." - echo "Please report to the ConTeXt mailing-list (ntg-context@ntg.nl)" -fi - -# -# PATH -# - -# this resolves to path of the setuptex script -# We use $0 for determine the path to the script, except for: -# * bash where $0 always is bash; here we use BASH_SOURCE -# * ksh93 where we use ${.sh.file} -# Thanks to Vasile Gaburici and Alessandro Perucchi for reporting this -# * http://www.ntg.nl/pipermail/ntg-context/2008/033953.html -# * http://www.ntg.nl/pipermail/ntg-context/2012/068658.html -if [ z"$BASH_SOURCE" != z ]; then - SCRIPTPATH="$BASH_SOURCE" -elif [ z"$KSH_VERSION" != z ]; then - SCRIPTPATH="${.sh.file}" -else - SCRIPTPATH="$0" -fi - -OWNPATH=$(cd -P -- "$(dirname -- "$SCRIPTPATH")" && pwd -P) - -# but one can also call -# . setuptex path-to-tree - -TEXROOT="" -# first check if any path has been provided in the argument, and try to use that one -if [ $# -ne 0 ] ; then - # TODO: resolve any errors - ARGPATH=$(cd -P -- "$(dirname -- "$1")" && pwd -P) && ARGPATH=$ARGPATH/$(basename -- "$1") - if test -f "$ARGPATH/texmf/tex/plain/base/plain.tex" ; then - if [ -d "$ARGPATH/texmf-$platform/bin" ]; then - TEXROOT="$ARGPATH" - else - echo "Binaries for platform '$platform' are missing." - echo "(There is no folder \"$ARGPATH/texmf-$platform/bin\")" - fi - else - echo "The argument \"$ARGPATH\" is not a valid TEXROOT path." - echo "(There is no file \"$ARGPATH/texmf/tex/plain/base/plain.tex\")" - - if [ -f "$OWNPATH/texmf/tex/plain/base/plain.tex" ]; then - TEXROOT="$OWNPATH" - fi - fi -else - if [ -f "$OWNPATH/texmf/tex/plain/base/plain.tex" ]; then - if [ -d "$OWNPATH/texmf-$platform/bin" ]; then - TEXROOT="$OWNPATH" - else - echo "Binaries for platform '$platform' are missing." - echo "(There is no folder \"$OWNPATH/texmf-$platform/bin\")" - fi - else - echo "\"$OWNPATH\" is not a valid TEXROOT path." - echo "(There is no file \"$OWNPATH/texmf/tex/plain/base/plain.tex\")" - fi -fi - -if [ "$TEXROOT" != "" ]; then - # for Alan Braslau's server :) - if [ "x$PS1" != "x" ] ; then - echo "Setting \"$TEXROOT\" as ConTeXt root." - fi - -# ConTeXt binaries have to be added to PATH -TEXMFOS=$TEXROOT/texmf-$platform -export PATH=$TEXMFOS/bin:$PATH - -# unset variables that won't be used lately -unset platform cpu system OWNPATH SCRIPTPATH ARGPATH TEXMFOS - -# not sure why this would be needed -# export CTXMINIMAL=yes - -else - echo "provide a proper tex root (like '. setuptex /something/tex')" ; -fi - diff --git a/scripts/context/stubs/setup/setuptex.csh b/scripts/context/stubs/setup/setuptex.csh deleted file mode 100644 index c1160675f..000000000 --- a/scripts/context/stubs/setup/setuptex.csh +++ /dev/null @@ -1,164 +0,0 @@ -# Example setup file for ConTeXt distribution -# -# Author: Hans Hagen -# Patches: Arthur R. & Mojca M. -# (t)csh version: Alan B. -# -# Usage : -# source setuptex.csh [texroot] -# -# On the first run also execute: -# mktexlsr -# texexec --make --alone - -echo "We are considering removing setuptex.csh in case that nobody uses it." -echo "If you still use this file please drop us some mail at" -echo " gardeners (at) contextgarden (dot) net" -echo "If we don't get any response, we will delete it in near future." - -# -# PLATFORM -# - -# we will try to guess the platform first -# (needs to be kept in sync with first-setup.sh and mtxrun) -# if yours is missing, let us know - -set system=`uname -s` -set cpu=`uname -m` - -switch ( $system ) - # linux - case Linux: - switch ( $cpu ) - case i*86: - set platform="linux" - breaksw - case x86_64: - case ia64: - set platform="linux-64" - breaksw - case ppc: - case ppc64: - set platform="linux-ppc" - breaksw - default: - set platform="unknown" - endsw - breaksw - # Mac OS X - case Darwin: - switch ( $cpu ) - case i*86: - set platform="osx-intel" - breaksw - case x86_64: - set platform="osx-64" - breaksw - case ppc*: - case powerpc: - case power*: - case Power*: - set platform="osx-ppc" - breaksw - default: - set platform="unknown" - endsw - breaksw - # FreeBSD - case FreeBSD: - case freebsd: - switch ( $cpu ) - case i*86: - set platform="freebsd" - breaksw - case x86_64: - set platform="freebsd" - breaksw - case amd64: - set platform="freebsd-amd64" - breaksw - default: - set platform="unknown" - endsw - breaksw - # cygwin - case CYGWIN: - switch ( $cpu ) - case i*86: - set platform="cygwin" - breaksw - case x86_64: - case ia64: - set platform="cygwin-64" - breaksw - default: - set platform="unknown" - endsw - breaksw - # SunOS/Solaris - case SunOS: - switch ( $cpu ) - case sparc: - set platform="solaris-sparc" - breaksw - case i86pc: - set platform="solaris-intel" - default: - set platform="unknown" - endsw - breaksw - # Other - default: - set platform="unknown" -endsw - -if ( $platform == "unknown" ) then - echo Error: your system \"$system $cpu\" is not supported yet. - echo Please report to the ConTeXt mailing-list (ntg-context@ntg.nl). -endif - -# -# PATH -# - -# this resolves to path of the setuptex script -# We use $0 for determine the path to the script, except for bash and (t)csh where $0 -# always is bash or (t)csh. - -# but one can also call -# . setuptex path-to-tex-tree - -# first check if any path has been provided in the argument, and try to use that one -if ( $# > 0 ) then - setenv TEXROOT $1 -else - # $_ should be `history -h 1` but doesn't seem to work... - set cmd=`history -h 1` - if ( $cmd[2]:h == $cmd[2]:t ) then - setenv TEXROOT $cwd - else - setenv TEXROOT $cmd[2]:h - endif - unset cmd -endif -cd $TEXROOT; setenv TEXROOT $cwd; cd - - -if ( -f "$TEXROOT/texmf/tex/plain/base/plain.tex" ) then - echo Setting \"$TEXROOT\" as TEXROOT. -else - echo \"$TEXROOT\" is not a valid TEXROOT path. - echo There is no file \"$TEXROOT/texmf/tex/plain/base/plain.tex\". - echo Please provide a proper tex root (like \"source setuptex /path/tex\") - unsetenv TEXROOT - exit -endif - -unsetenv TEXINPUTS MPINPUTS MFINPUTS - -# ConTeXt binaries have to be added to PATH -setenv TEXMFOS $TEXROOT/texmf-$platform -setenv PATH $TEXMFOS/bin:$PATH -# TODO: we could set OSFONTDIR on Mac for example - -# setenv CTXMINIMAL yes diff --git a/scripts/context/stubs/source/mtxrun_dll.c b/scripts/context/stubs/source/mtxrun_dll.c index fc2e260f5..400ed6778 100644 --- a/scripts/context/stubs/source/mtxrun_dll.c +++ b/scripts/context/stubs/source/mtxrun_dll.c @@ -55,6 +55,7 @@ return 1; \ } +char texlua_name[] = "texlua"; // just a bare name, luatex strips the rest anyway static char cmdline[MAX_CMD]; static char dirpath[MAX_PATH]; static char progname[MAX_PATH]; @@ -69,12 +70,12 @@ int main( int argc, char *argv[] ) __declspec(dllexport) int dllrunscript( int argc, char *argv[] ) #endif { - char *binary, *s, *luatexfname, *argstr, **lua_argv; + char *s, *luatexfname, *argstr, **lua_argv; int k, quoted, lua_argc; int passprogname = 0; - unsigned char is_jit=0; // directory of this module/executable + HMODULE module_handle = GetModuleHandle( "mtxrun.dll" ); // if ( module_handle == NULL ) exe path will be used, which is OK too k = (int) GetModuleFileName( module_handle, dirpath, MAX_PATH ); @@ -85,20 +86,13 @@ __declspec(dllexport) int dllrunscript( int argc, char *argv[] ) *(++s) = '\0'; //remove file name, leave trailing backslash // program name + k = strlen(argv[0]); while ( k && (argv[0][k-1] != '/') && (argv[0][k-1] != '\\') ) k--; strcpy(progname, &argv[0][k]); s = progname; if ( s = strrchr(s, '.') ) *s = '\0'; // remove file extension part - /* check "jit" : strlen("jit") = 3 */ - if (strncmp(progname + strlen(progname) - 3, "jit", 3) == 0) { - is_jit = 1; - progname[strlen(progname) - 3]='\0'; - } - else - is_jit = 0; - // script path strcpy( scriptpath, dirpath ); @@ -120,110 +114,44 @@ __declspec(dllexport) int dllrunscript( int argc, char *argv[] ) strcat( scriptpath, "mtxrun.lua" ); passprogname = 1; } + if ( GetFileAttributes(scriptpath) == INVALID_FILE_ATTRIBUTES ) DIE( "file not found: %s\n", scriptpath ); - // find luatex.exe /luajittex.exe - if ( SearchPath( - dirpath, // was getenv( "PATH" ), // path to search (optional) - (is_jit ? "luajittex.exe":"luatex.exe"), // file name to search - NULL, // file extension to add (optional) - MAX_PATH, // output buffer size - luatexpath, // output buffer pointer - &luatexfname ) // pointer to a file part in the output buffer (optional) - ) { - binary = (is_jit ? "luajittex.exe":"luatex.exe"); - } else if ( SearchPath( - dirpath, // was getenv( "PATH" ), // path to search (optional) - (is_jit ? "texluajit.exe":"texlua.exe"), // file name to search - NULL, // file extension to add (optional) - MAX_PATH, // output buffer size - luatexpath, // output buffer pointer - &luatexfname ) // pointer to a file part in the output buffer (optional) - ) { - binary = (is_jit ? "texluajit.exe":"texlua.exe"); - } else if ( SearchPath( - getenv("PATH"), // was dirpath, // path to search (optional) - (is_jit ? "luajittex.exe":"luatex.exe"), // file name to search - NULL, // file extension to add (optional) - MAX_PATH, // output buffer size - luatexpath, // output buffer pointer - &luatexfname ) // pointer to a file part in the output buffer (optional) - ) { - binary = (is_jit ? "luajittex.exe":"luatex.exe"); - } else if ( SearchPath( - getenv("PATH") , // was dirpath, // path to search (optional) - (is_jit ? "texluajit.exe":"texlua.exe"), // file name to search - NULL, // file extension to add (optional) - MAX_PATH, // output buffer size - luatexpath, // output buffer pointer - &luatexfname ) // pointer to a file part in the output buffer (optional) - ) { - binary = (is_jit ? "texluajit.exe":"texlua.exe"); - }else { - DIE( "unable to locate texlua.exe on the search path" ); - } - - /* if ( SearchPath( */ - /* dirpath, // was getenv( "PATH" ), // path to search (optional) */ - /* (is_jit ? "luajittex.exe":"luatex.exe"), // file name to search */ - /* NULL, // file extension to add (optional) */ - /* MAX_PATH, // output buffer size */ - /* luatexpath, // output buffer pointer */ - /* &luatexfname ) // pointer to a file part in the output buffer (optional) */ - /* ) { */ - /* binary = (is_jit ? "luajittex.exe":"luatex.exe"); */ - /* }else if ( SearchPath( */ - /* getenv("PATH"), // was dirpath, // path to search (optional) */ - /* (is_jit ? "luajittex.exe":"luatex.exe"), // file name to search */ - /* NULL, // file extension to add (optional) */ - /* MAX_PATH, // output buffer size */ - /* luatexpath, // output buffer pointer */ - /* &luatexfname ) // pointer to a file part in the output buffer (optional) */ - /* ) { */ - /* binary = (is_jit ? "luajittex.exe":"luatex.exe"); */ - /* }else if ( SearchPath( */ - /* dirpath, // was getenv( "PATH" ), // path to search (optional) */ - /* (is_jit ? "texluajit.exe":"texlua.exe"), // file name to search */ - /* NULL, // file extension to add (optional) */ - /* MAX_PATH, // output buffer size */ - /* luatexpath, // output buffer pointer */ - /* &luatexfname ) // pointer to a file part in the output buffer (optional) */ - /* ) { */ - /* binary = (is_jit ? "texluajit.exe":"texlua.exe"); */ - /* }else if ( SearchPath( */ - /* getenv("PATH") , // was dirpath, // path to search (optional) */ - /* (is_jit ? "texluajit.exe":"texlua.exe"), // file name to search */ - /* NULL, // file extension to add (optional) */ - /* MAX_PATH, // output buffer size */ - /* luatexpath, // output buffer pointer */ - /* &luatexfname ) // pointer to a file part in the output buffer (optional) */ - /* ) { */ - /* binary = (is_jit ? "texluajit.exe":"texlua.exe"); */ - /* }else { */ - /* DIE( "unable to locate texlua.exe on the search path" ); */ - /* } */ - - - + // find texlua.exe + + if ( !SearchPath( + getenv( "PATH" ), // path to search (optional) + "texlua.exe", // file name to search + NULL, // file extension to add (optional) + MAX_PATH, // output buffer size + luatexpath, // output buffer pointer + &luatexfname ) // pointer to a file part in the output buffer (optional) + ) + if ( !SearchPath( + dirpath, // path to search (optional) + "texlua.exe", // file name to search + NULL, // file extension to add (optional) + MAX_PATH, // output buffer size + luatexpath, // output buffer pointer + &luatexfname ) // pointer to a file part in the output buffer (optional) + ) + DIE( "unable to locate texlua.exe on the search path" ); // link directly with luatex.dll if available in texlua's dir - strcpy( luatexfname, (is_jit ? "luajittex.dll":"luatex.dll") ); + + strcpy( luatexfname, "luatex.dll" ); if ( dllluatex = LoadLibrary(luatexpath) ) { - mainlikeproc dllluatexmain = (mainlikeproc) GetProcAddress( dllluatex, (is_jit ? "dllluajittexmain": "dllluatexmain" )); + mainlikeproc dllluatexmain = (mainlikeproc) GetProcAddress( dllluatex, "dllluatexmain" ); if ( dllluatexmain == NULL ) - if (is_jit) - DIE( "unable to locate dllluatexmain procedure in luajittex.dll" ) - else - DIE( "unable to locate dllluatexmain procedure in luatex.dll" ); + DIE( "unable to locate dllluatexmain procedure in luatex.dll" ); // set up argument list for texlua script - lua_argv = (char **)malloc( (argc + 5) * sizeof(char *) ); + lua_argv = (char **)malloc( (argc + 4) * sizeof(char *) ); if ( lua_argv == NULL ) DIE( "out of memory\n" ); - lua_argv[lua_argc=0] = luatexfname; - lua_argv[++lua_argc] = "--luaonly"; + lua_argv[lua_argc=0] = texlua_name; lua_argv[++lua_argc] = scriptpath; // script to execute if (passprogname) { lua_argv[++lua_argc] = "--script"; @@ -234,15 +162,15 @@ __declspec(dllexport) int dllrunscript( int argc, char *argv[] ) // call texlua interpreter // dllluatexmain never returns, but we pretend that it does - + k = dllluatexmain( lua_argc, lua_argv ); if (lua_argv) free( lua_argv ); return k; } + // we are still here, so no luatex.dll; spawn texlua.exe instead - strcpy( luatexfname,binary); - strcpy( cmdline, " --luaonly " ); + strcpy( luatexfname, "texlua.exe" ); strcpy( cmdline, "\"" ); strcat( cmdline, luatexpath ); strcat( cmdline, "\" \"" ); @@ -252,6 +180,7 @@ __declspec(dllexport) int dllrunscript( int argc, char *argv[] ) strcat( cmdline, " --script " ); strcat( cmdline, progname ); } + argstr = GetCommandLine(); // get the command line of this process if ( argstr == NULL ) DIE( "unable to retrieve the command line string\n" ); @@ -280,6 +209,7 @@ __declspec(dllexport) int dllrunscript( int argc, char *argv[] ) si.hStdOutput = GetStdHandle( STD_OUTPUT_HANDLE ); si.hStdError = GetStdHandle( STD_ERROR_HANDLE ); ZeroMemory( &pi, sizeof(pi) ); + if( !CreateProcess( NULL, // module name (uses command line if NULL) cmdline, // command line @@ -292,6 +222,7 @@ __declspec(dllexport) int dllrunscript( int argc, char *argv[] ) &si, // STARTUPINFO structure &pi ) // PROCESS_INFORMATION structure ) DIE( "command execution failed: %s\n", cmdline ); + DWORD ret = 0; CloseHandle( pi.hThread ); // thread handle is not needed if ( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 ) { @@ -301,6 +232,7 @@ __declspec(dllexport) int dllrunscript( int argc, char *argv[] ) CloseHandle( pi.hProcess ); // propagate exit code from the child process + return ret; } diff --git a/scripts/context/stubs/source/readme.txt b/scripts/context/stubs/source/readme.txt index 72892ee2f..354d85b09 100644 --- a/scripts/context/stubs/source/readme.txt +++ b/scripts/context/stubs/source/readme.txt @@ -1,40 +1,36 @@ Copyright: -The originally 'runscript' program was written by in 2009 by T.M.Trzeciak and is -public domain. This derived mtxrun program is an adapted version by Hans Hagen and -Luigi Scarso. +The originally 'runscript' program was written by in 2009 by +T.M.Trzeciak and is public domain. This derived mtxrun program +is an adapted version by Hans Hagen. Comment: -In ConTeXt MkIV we have two core scripts: luatools.lua and mtxrun.lua where the -second one is used to launch other scripts. The mtxrun.exe program calls luatex.exe. - +In ConTeXt MkIV we have two core scripts: luatools.lua and +mtxrun.lua where the second one is used to launch other scripts. Normally a user will use a call like: - mtxrun --script font --reload - -Here mtxrun is a lua script. In order to avoid the usage of a cmd file on windows this -runner will start texlua directly. In TeXlive a runner is added for each cmd file but -we don't want that overhead (and extra files). By using an exe we can call these -scripts in batch files without the need for using call. - -The mtxrun.exe file can be copied to a mtxrunjit.exe file in which case luajittex.exe -is called. +mtxrun --script font --reload - mtxrunjit --script font --reload +Here mtxrun is a lua script. In order to avoid the usage of a cmd +file on windows this runner will start texlua directly. In TeXlive +a runner is added for each cmd file but we don't want that overhead +(and extra files). By using an exe we can call these scripts in +batch files without the need for using call. -We also don't want to use other runners, like those that use kpse to locate the script -as this is exactly what mtxrun itself is doing already. Therefore the runscript program -is adapted to a more direct approach suitable for mtxrun. +We also don't want to use other runners, like those that use kpse +to locate the script as this is exactly what mtxrun itself is doing +already. Therefore the runscript program is adapted to a more direct +approach suitable for mtxrun. Compilation: with gcc (size optimized): - gcc -Os -s -shared -o mtxrun.dll mtxrun_dll.c - gcc -Os -s -o mtxrun.exe mtxrun_exe.c -L./ -lmtxrun +gcc -Os -s -shared -o mtxrun.dll mtxrun_dll.c +gcc -Os -s -o mtxrun.exe mtxrun_exe.c -L./ -lmtxrun with tcc (ver. 0.9.24), extra small size - tcc -shared -o runscript.dll runscript_dll.c - tcc -o runscript.exe runscript_exe.c runscript.def +tcc -shared -o runscript.dll runscript_dll.c +tcc -o runscript.exe runscript_exe.c runscript.def diff --git a/scripts/context/stubs/unix/contextjit b/scripts/context/stubs/unix/contextjit deleted file mode 100644 index 5ac1947c7..000000000 --- a/scripts/context/stubs/unix/contextjit +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -luajittex --luaonly $(dirname $0)/mtxrun --script context "$@" - -# luajittex --luaonly ${0%contextjit}mtxrun --script context "$@" diff --git a/scripts/context/stubs/unix/ctxtools b/scripts/context/stubs/unix/ctxtools new file mode 100644 index 000000000..2e6bd4afa --- /dev/null +++ b/scripts/context/stubs/unix/ctxtools @@ -0,0 +1,2 @@ +#!/bin/sh +mtxrun --script ctxtools "$@" diff --git a/scripts/context/stubs/unix/mptopdf b/scripts/context/stubs/unix/mptopdf new file mode 100644 index 000000000..147333740 --- /dev/null +++ b/scripts/context/stubs/unix/mptopdf @@ -0,0 +1,2 @@ +#!/bin/sh +mtxrun --script mptopdf "$@" diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun index 3372831b3..0ff2d2897 100644 --- a/scripts/context/stubs/unix/mtxrun +++ b/scripts/context/stubs/unix/mtxrun @@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lua"] = package.loaded["l-lua"] or true --- original size: 3247, stripped down to: 1763 +-- original size: 3123, stripped down to: 1694 if not modules then modules={} end modules ['l-lua']={ version=1.001, @@ -136,9 +136,6 @@ function optionalrequire(...) return result end end -if lua then - lua.mask=load([[τεχ = 1]]) and "utf" or "ascii" -end end -- of closure @@ -437,7 +434,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 29808, stripped down to: 16182 +-- original size: 29245, stripped down to: 15964 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -453,9 +450,7 @@ local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.forma local floor=math.floor local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print -if setinspector then - setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) -end +setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) lpeg.patterns=lpeg.patterns or {} local patterns=lpeg.patterns local anything=P(1) @@ -524,11 +519,9 @@ patterns.spacer=spacer patterns.whitespace=whitespace patterns.nonspacer=nonspacer patterns.nonwhitespace=nonwhitespace -local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) -local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0) +local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0)) patterns.stripper=stripper -patterns.fullstripper=fullstripper patterns.collapser=collapser patterns.lowercase=lowercase patterns.uppercase=uppercase @@ -751,7 +744,7 @@ function lpeg.replacer(one,two,makefunction,isutf) return pattern end end -function lpeg.finder(lst,makefunction,isutf) +function lpeg.finder(lst,makefunction) local pattern if type(lst)=="table" then pattern=P(false) @@ -767,11 +760,7 @@ function lpeg.finder(lst,makefunction,isutf) else pattern=P(lst) end - if isutf then - pattern=((utf8char or 1)-pattern)^0*pattern - else - pattern=(1-pattern)^0*pattern - end + pattern=(1-pattern)^0*pattern if makefunction then return function(str) return lpegmatch(pattern,str) @@ -1082,7 +1071,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-string"] = package.loaded["l-string"] or true --- original size: 5671, stripped down to: 2827 +-- original size: 5547, stripped down to: 2708 if not modules then modules={} end modules ['l-string']={ version=1.001, @@ -1118,15 +1107,11 @@ function string.limit(str,n,sentinel) end end local stripper=patterns.stripper -local fullstripper=patterns.fullstripper local collapser=patterns.collapser local longtostring=patterns.longtostring function string.strip(str) return lpegmatch(stripper,str) or "" end -function string.fullstrip(str) - return lpegmatch(fullstripper,str) or "" -end function string.collapsespaces(str) return lpegmatch(collapser,str) or "" end @@ -1187,7 +1172,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-table"] = package.loaded["l-table"] or true --- original size: 31142, stripped down to: 20283 +-- original size: 31113, stripped down to: 20256 if not modules then modules={} end modules ['l-table']={ version=1.001, @@ -2015,9 +2000,7 @@ function table.print(t,...) serialize(print,t,...) end end -if setinspector then - setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) -end +setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) function table.sub(t,i,j) return { unpack(t,i,j) } end @@ -3524,7 +3507,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-url"] = package.loaded["l-url"] or true --- original size: 12292, stripped down to: 5585 +-- original size: 11993, stripped down to: 5584 if not modules then modules={} end modules ['l-url']={ version=1.001, @@ -3551,7 +3534,7 @@ local hexdigit=R("09","AF","af") local plus=P("+") local nothing=Cc("") local escapedchar=(percent*C(hexdigit*hexdigit))/tochar -local escaped=(plus/" ")+escapedchar +local escaped=(plus/" ")+escapedchar local noslash=P("/")/"" local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2) local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0) @@ -3735,7 +3718,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-dir"] = package.loaded["l-dir"] or true --- original size: 14768, stripped down to: 9107 +-- original size: 14229, stripped down to: 8740 if not modules then modules={} end modules ['l-dir']={ version=1.001, @@ -3758,7 +3741,6 @@ local isdir=lfs.isdir local isfile=lfs.isfile local currentdir=lfs.currentdir local chdir=lfs.chdir -local mkdir=lfs.mkdir local onwindows=os.type=="windows" or find(os.getenv("PATH"),";") if not isdir then function isdir(name) @@ -3931,27 +3913,16 @@ end local make_indeed=true if onwindows then function dir.mkdirs(...) - local n=select("#",...) - local str - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - local s=select(i,...) - if s=="" then - elseif str=="" then - str=s - else - str=str.."/"..s - end + local str,pth="","" + for i=1,select("#",...) do + local s=select(i,...) + if s=="" then + elseif str=="" then + str=s + else + str=str.."/"..s end end - local pth="" local drive=false local first,middle,last=match(str,"^(//)(//*)(.*)$") if first then @@ -3986,30 +3957,21 @@ if onwindows then pth=pth.."/"..s end if make_indeed and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end return pth,(isdir(pth)==true) end else function dir.mkdirs(...) - local n=select("#",...) - local str,pth - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - if s and s~="" then - if str~="" then - str=str.."/"..s - else - str=s - end + local str,pth="","" + for i=1,select("#",...) do + local s=select(i,...) + if s and s~="" then + if str~="" then + str=str.."/"..s + else + str=s end end end @@ -4024,7 +3986,7 @@ else pth=pth.."/"..s end if make_indeed and not first and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end else @@ -4032,7 +3994,7 @@ else for s in gmatch(str,"[^/]+") do pth=pth.."/"..s if make_indeed and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end end @@ -4840,7 +4802,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 29502, stripped down to: 16632 +-- original size: 26857, stripped down to: 15062 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -4859,19 +4821,8 @@ local unpack,concat=table.unpack,table.concat local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc local patterns,lpegmatch=lpeg.patterns,lpeg.match local utfchar,utfbyte=utf.char,utf.byte -local loadstripped=nil -if _LUAVERSION<5.2 then - loadstripped=function(str,shortcuts) - return load(str) - end -else - loadstripped=function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end +local loadstripped=_LUAVERSION<5.2 and load or function(str) + return load(dump(load(str),true)) end if not number then number={} end local stripper=patterns.stripzeros @@ -5021,58 +4972,31 @@ function number.sparseexponent(f,n) end return tostring(n) end +local preamble=[[ +local type = type +local tostring = tostring +local tonumber = tonumber +local format = string.format +local concat = table.concat +local signed = number.signed +local points = number.points +local basepoints = number.basepoints +local utfchar = utf.char +local utfbyte = utf.byte +local lpegmatch = lpeg.match +local nspaces = string.nspaces +local tracedchar = string.tracedchar +local autosingle = string.autosingle +local autodouble = string.autodouble +local sequenced = table.sequenced +local formattednumber = number.formatted +local sparseexponent = number.sparseexponent +]] local template=[[ %s %s return function(%s) return %s end ]] -local preamble,environment="",{} -if _LUAVERSION<5.2 then - preamble=[[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] -else - environment={ - global=global or _G, - lpeg=lpeg, - type=type, - tostring=tostring, - tonumber=tonumber, - format=string.format, - concat=table.concat, - signed=number.signed, - points=number.points, - basepoints=number.basepoints, - utfchar=utf.char, - utfbyte=utf.byte, - lpegmatch=lpeg.match, - nspaces=string.nspaces, - tracedchar=string.tracedchar, - autosingle=string.autosingle, - autodouble=string.autodouble, - sequenced=table.sequenced, - formattednumber=number.formatted, - sparseexponent=number.sparseexponent, - } -end local arguments={ "a1" } setmetatable(arguments,{ __index=function(t,k) local v=t[k-1]..",a"..k @@ -5394,8 +5318,8 @@ local builder=Cs { "start", ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension, } local direct=Cs ( - P("%")*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*P(-1)/[[local format = string.format return function(str) return format("%0",str) end]] -) + P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1) + ) local function make(t,str) local f local p @@ -5407,7 +5331,7 @@ local function make(t,str) p=lpegmatch(builder,str,1,"..",t._extensions_) if n>0 then p=format(template,preamble,t._preamble_,arguments[n],p) - f=loadstripped(p,t._environment_)() + f=loadstripped(p)() else f=function() return str end end @@ -5419,22 +5343,10 @@ local function use(t,fmt,...) return t[fmt](...) end strings.formatters={} -if _LUAVERSION<5.2 then - function strings.formatters.new() - local t={ _extensions_={},_preamble_=preamble,_environment_={},_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end -else - function strings.formatters.new() - local e={} - for k,v in next,environment do - e[k]=v - end - local t={ _extensions_={},_preamble_="",_environment_=e,_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end +function strings.formatters.new() + local t={ _extensions_={},_preamble_="",_type_="formatter" } + setmetatable(t,{ __index=make,__call=use }) + return t end local formatters=strings.formatters.new() string.formatters=formatters @@ -5442,12 +5354,8 @@ string.formatter=function(str,...) return formatters[str](...) end local function add(t,name,template,preamble) if type(t)=="table" and t._type_=="formatter" then t._extensions_[name]=template or "%s" - if type(preamble)=="string" then + if preamble then t._preamble_=preamble.."\n"..t._preamble_ - elseif type(preamble)=="table" then - for k,v in next,preamble do - t._environment_[k]=v - end end end end @@ -5456,15 +5364,9 @@ patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"" patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) -if _LUAVERSION<5.2 then - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") -else - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape }) -end +add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) +add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) +add(formatters,"lua",[[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) end -- of closure @@ -5473,7 +5375,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 23980, stripped down to: 16119 +-- original size: 23952, stripped down to: 16092 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -5708,7 +5610,7 @@ local f_ordered_string=formatters["%q,"] local f_ordered_number=formatters["%s,"] local f_ordered_boolean=formatters["%l,"] function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } + local r={ prefix or "return" } local m=1 local function fastserialize(t,outer) local n=#t @@ -7747,7 +7649,7 @@ do -- create closure to overcome 200 locals limit package.loaded["trac-inf"] = package.loaded["trac-inf"] or true --- original size: 6643, stripped down to: 5272 +-- original size: 6501, stripped down to: 5156 if not modules then modules={} end modules ['trac-inf']={ version=1.001, @@ -7848,10 +7750,7 @@ function statistics.show() if statistics.enable then local register=statistics.register register("used platform",function() - local mask=lua.mask or "ascii" - return format("%s, type: %s, binary subtree: %s, symbol mask: %s (%s)", - os.platform or "unknown",os.type or "unknown",environment.texos or "unknown", - mask,mask=="utf" and "τεχ" or "tex") + return format("%s, type: %s, binary subtree: %s",os.platform or "unknown",os.type or "unknown",environment.texos or "unknown") end) register("luatex banner",function() return lower(status.banner) @@ -7930,7 +7829,7 @@ do -- create closure to overcome 200 locals limit package.loaded["trac-pro"] = package.loaded["trac-pro"] or true --- original size: 5829, stripped down to: 3501 +-- original size: 5773, stripped down to: 3453 if not modules then modules={} end modules ['trac-pro']={ version=1.001, @@ -7947,16 +7846,14 @@ local namespaces=namespaces local registered={} local function report_index(k,name) if trace_namespaces then - report_system("reference to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) + report_system("reference to %a in protected namespace %a: %s",k,name,debug.traceback()) else report_system("reference to %a in protected namespace %a",k,name) end end local function report_newindex(k,name) if trace_namespaces then - report_system("assignment to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) + report_system("assignment to %a in protected namespace %a: %s",k,name,debug.traceback()) else report_system("assignment to %a in protected namespace %a",k,name) end @@ -8207,7 +8104,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-deb"] = package.loaded["util-deb"] or true --- original size: 3898, stripped down to: 2644 +-- original size: 3708, stripped down to: 2568 if not modules then modules={} end modules ['util-deb']={ version=1.001, @@ -8287,22 +8184,20 @@ end function debugger.disable() debug.sethook() end -local function showtraceback(rep) - local level=2 - local reporter=rep or report +function traceback() + local level=1 while true do - local info=getinfo(level,"Sl") + local info=debug.getinfo(level,"Sl") if not info then break elseif info.what=="C" then - reporter("%2i : %s",level-1,"C function") + print(format("%3i : C function",level)) else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) + print(format("%3i : [%s]:%d",level,info.short_src,info.currentline)) end level=level+1 end end -debugger.showtraceback=showtraceback end -- of closure @@ -8968,7 +8863,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true --- original size: 42614, stripped down to: 26694 +-- original size: 42447, stripped down to: 26589 if not modules then modules={} end modules ['lxml-tab']={ version=1.001, @@ -9494,11 +9389,8 @@ local function _xmlconvert_(data,settings) end if errorstr and errorstr~="" then result.error=true - else - errorstr=nil end result.statistics={ - errormessage=errorstr, entities={ decimals=dcache, hexadecimals=hcache, @@ -9696,26 +9588,24 @@ local function verbose_document(e,handlers) end end local function serialize(e,handlers,...) - if e then - local initialize=handlers.initialize - local finalize=handlers.finalize - local functions=handlers.functions - if initialize then - local state=initialize(...) - if not state==true then - return state - end - end - local etg=e.tg - if etg then - (functions[etg] or functions["@el@"])(e,handlers) - else - functions["@dc@"](e,handlers) - end - if finalize then - return finalize() + local initialize=handlers.initialize + local finalize=handlers.finalize + local functions=handlers.functions + if initialize then + local state=initialize(...) + if not state==true then + return state end end + local etg=e.tg + if etg then + (functions[etg] or functions["@el@"])(e,handlers) + else + functions["@dc@"](e,handlers) + end + if finalize then + return finalize() + end end local function xserialize(e,handlers) local functions=handlers.functions @@ -15485,7 +15375,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-use"] = package.loaded["data-use"] or true --- original size: 3899, stripped down to: 2984 +-- original size: 3913, stripped down to: 2998 if not modules then modules={} end modules ['data-use']={ version=1.001, @@ -15531,7 +15421,7 @@ end statistics.register("used config file",function() return caches.configfiles() end) statistics.register("used cache path",function() return caches.usedpaths() end) function statistics.savefmtstatus(texname,formatbanner,sourcefile) - local enginebanner=status.banner + local enginebanner=status.list().banner if formatbanner and enginebanner and sourcefile then local luvname=file.replacesuffix(texname,"luv") local luvdata={ @@ -15544,7 +15434,7 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile) end end function statistics.checkfmtstatus(texname) - local enginebanner=status.banner + local enginebanner=status.list().banner if enginebanner and texname then local luvname=file.replacesuffix(texname,"luv") if lfs.isfile(luvname) then @@ -16168,7 +16058,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-aux"] = package.loaded["data-aux"] or true --- original size: 2431, stripped down to: 1996 +-- original size: 2394, stripped down to: 2005 if not modules then modules={} end modules ['data-aux']={ version=1.001, @@ -16182,8 +16072,8 @@ local type,next=type,next local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) local resolvers=resolvers local report_scripts=logs.reporter("resolvers","scripts") -function resolvers.updatescript(oldname,newname) - local scriptpath="context/lua" +function resolvers.updatescript(oldname,newname) + local scriptpath="scripts/context/lua" newname=file.addsuffix(newname,"lua") local oldscript=resolvers.cleanpath(oldname) if trace_locating then @@ -16791,8 +16681,8 @@ end -- of closure -- used libraries : l-lua.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 689993 --- stripped bytes : 244562 +-- original bytes : 685064 +-- stripped bytes : 242353 -- end library merge @@ -16891,18 +16781,17 @@ local ownlibs = { -- order can be made better } --- c:/data/develop/tex-context/tex/texmf-win64/bin/../../texmf-context/tex/context/base/data-tmf.lua --- c:/data/develop/context/sources/data-tmf.lua - local ownlist = { - -- '.', - -- ownpath , - owntree .. "/../../../../context/sources", -- HH's development path + '.', + ownpath , + ownpath .. "/../sources", -- HH's development path owntree .. "/../../texmf-local/tex/context/base", owntree .. "/../../texmf-context/tex/context/base", + owntree .. "/../../texmf-dist/tex/context/base", owntree .. "/../../texmf/tex/context/base", owntree .. "/../../../texmf-local/tex/context/base", owntree .. "/../../../texmf-context/tex/context/base", + owntree .. "/../../../texmf-dist/tex/context/base", owntree .. "/../../../texmf/tex/context/base", } @@ -17809,12 +17698,6 @@ if e_argument("ansi") then status_nop = formatters["[1;32m%-15s [0;1m:[0m\n"], } - local script = e_argument("script") or e_argument("scripts") - - if type(script) == "string" then - logs.writer("]0;"..script.."") -- for Alan to test - end - end if e_argument("script") or e_argument("scripts") then @@ -17838,16 +17721,8 @@ elseif e_argument("selfmerge") then runners.loadbase() local found = locate_libs() - if found then - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfmerge(mtxrun,own.libs,{ found }) - application.report("runner updated on resolved path: %s",mtxrun) - else - utilities.merger.selfmerge(own.name,own.libs,{ found }) - application.report("runner updated on relative path: %s",own.name) - end + utilities.merger.selfmerge(own.name,own.libs,{ found }) end elseif e_argument("selfclean") then @@ -17855,15 +17730,7 @@ elseif e_argument("selfclean") then -- remove embedded libraries runners.loadbase() - - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfclean(mtxrun) - application.report("runner cleaned on resolved path: %s",mtxrun) - else - utilities.merger.selfclean(own.name) - application.report("runner cleaned on relative path: %s",own.name) - end + utilities.merger.selfclean(own.name) elseif e_argument("selfupdate") then @@ -18105,8 +17972,6 @@ elseif e_argument("version") then application.version() - application.report("source path",environment.ownbin) - elseif e_argument("directives") then directives.show() diff --git a/scripts/context/stubs/unix/mtxrunjit b/scripts/context/stubs/unix/mtxrunjit deleted file mode 100644 index 117105aa5..000000000 --- a/scripts/context/stubs/unix/mtxrunjit +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -luajittex --luaonly $(dirname $0)/mtxrun "$@" - -# luajittex --luaonly ${0%jit} "$@" diff --git a/scripts/context/stubs/unix/pstopdf b/scripts/context/stubs/unix/pstopdf new file mode 100644 index 000000000..116f5f4a3 --- /dev/null +++ b/scripts/context/stubs/unix/pstopdf @@ -0,0 +1,2 @@ +#!/bin/sh +mtxrun --script pstopdf "$@" diff --git a/scripts/context/stubs/win64/context.exe b/scripts/context/stubs/win64/context.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/context.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/contextjit.exe b/scripts/context/stubs/win64/contextjit.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/contextjit.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/ctxtools.exe b/scripts/context/stubs/win64/ctxtools.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/ctxtools.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/luatools.exe b/scripts/context/stubs/win64/luatools.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/luatools.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/metatex.exe b/scripts/context/stubs/win64/metatex.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/metatex.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/mptopdf.exe b/scripts/context/stubs/win64/mptopdf.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/mptopdf.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/mtxrun.dll b/scripts/context/stubs/win64/mtxrun.dll Binary files differdeleted file mode 100644 index 910502735..000000000 --- a/scripts/context/stubs/win64/mtxrun.dll +++ /dev/null diff --git a/scripts/context/stubs/win64/mtxrun.exe b/scripts/context/stubs/win64/mtxrun.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/mtxrun.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/mtxrun.lua b/scripts/context/stubs/win64/mtxrun.lua deleted file mode 100644 index 3372831b3..000000000 --- a/scripts/context/stubs/win64/mtxrun.lua +++ /dev/null @@ -1,18175 +0,0 @@ -#!/usr/bin/env texlua - --- for k, v in next, _G.string do --- local tv = type(v) --- if tv == "table" then --- for kk, vv in next, v do --- print(k,kk,vv) --- end --- else --- print(tv,k,v) --- end --- end - -if not modules then modules = { } end modules ['mtxrun'] = { - version = 1.001, - comment = "runner, lua replacement for texmfstart.rb", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- one can make a stub: --- --- #!/bin/sh --- env LUATEXDIR=/....../texmf/scripts/context/lua luatex --luaonly mtxrun.lua "$@" - --- filename : mtxrun.lua --- comment : companion to context.tex --- author : Hans Hagen, PRAGMA-ADE, Hasselt NL --- copyright: PRAGMA ADE / ConTeXt Development Team --- license : see context related readme files - --- This script is based on texmfstart.rb but does not use kpsewhich to --- locate files. Although kpse is a library it never came to opening up --- its interface to other programs (esp scripting languages) and so we --- do it ourselves. The lua variant evolved out of an experimental ruby --- one. Interesting is that using a scripting language instead of c does --- not have a speed penalty. Actually the lua variant is more efficient, --- especially when multiple calls to kpsewhich are involved. The lua --- library also gives way more control. - --- to be done / considered --- --- support for --exec or make it default --- support for jar files (or maybe not, never used, too messy) --- support for $RUBYINPUTS cum suis (if still needed) --- remember for subruns: _CTX_K_V_#{original}_ --- remember for subruns: _CTX_K_S_#{original}_ --- remember for subruns: TEXMFSTART.#{original} [tex.rb texmfstart.rb] - --- begin library merge - - - -do -- create closure to overcome 200 locals limit - -package.loaded["l-lua"] = package.loaded["l-lua"] or true - --- original size: 3247, stripped down to: 1763 - -if not modules then modules={} end modules ['l-lua']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") -_MAJORVERSION=tonumber(major) or 5 -_MINORVERSION=tonumber(minor) or 1 -_LUAVERSION=_MAJORVERSION+_MINORVERSION/10 -if not lpeg then - lpeg=require("lpeg") -end -if loadstring then - local loadnormal=load - function load(first,...) - if type(first)=="string" then - return loadstring(first,...) - else - return loadnormal(first,...) - end - end -else - loadstring=load -end -if not ipairs then - local function iterate(a,i) - i=i+1 - local v=a[i] - if v~=nil then - return i,v - end - end - function ipairs(a) - return iterate,a,0 - end -end -if not pairs then - function pairs(t) - return next,t - end -end -if not table.unpack then - table.unpack=_G.unpack -elseif not unpack then - _G.unpack=table.unpack -end -if not package.loaders then - package.loaders=package.searchers -end -local print,select,tostring=print,select,tostring -local inspectors={} -function setinspector(inspector) - inspectors[#inspectors+1]=inspector -end -function inspect(...) - for s=1,select("#",...) do - local value=select(s,...) - local done=false - for i=1,#inspectors do - done=inspectors[i](value) - if done then - break - end - end - if not done then - print(tostring(value)) - end - end -end -local dummy=function() end -function optionalrequire(...) - local ok,result=xpcall(require,dummy,...) - if ok then - return result - end -end -if lua then - lua.mask=load([[τεχ = 1]]) and "utf" or "ascii" -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-package"] = package.loaded["l-package"] or true - --- original size: 10587, stripped down to: 7815 - -if not modules then modules={} end modules ['l-package']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type=type -local gsub,format,find=string.gsub,string.format,string.find -local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match -local package=package -local searchers=package.searchers or package.loaders -local filejoin=file and file.join or function(path,name) return path.."/"..name end -local isreadable=file and file.is_readable or function(name) local f=io.open(name) if f then f:close() return true end end -local addsuffix=file and file.addsuffix or function(name,suffix) return name.."."..suffix end -local function cleanpath(path) - return path -end -local pattern=Cs((((1-S("\\/"))^0*(S("\\/")^1/"/"))^0*(P(".")^1/"/"+P(1))^1)*-1) -local function lualibfile(name) - return lpegmatch(pattern,name) or name -end -local offset=luarocks and 1 or 0 -local helpers=package.helpers or { - cleanpath=cleanpath, - lualibfile=lualibfile, - trace=false, - report=function(...) print(format(...)) end, - builtin={ - ["preload table"]=searchers[1+offset], - ["path specification"]=searchers[2+offset], - ["cpath specification"]=searchers[3+offset], - ["all in one fallback"]=searchers[4+offset], - }, - methods={}, - sequence={ - "already loaded", - "preload table", - "qualified path", - "lua extra list", - "lib extra list", - "path specification", - "cpath specification", - "all in one fallback", - "not loaded", - } -} -package.helpers=helpers -local methods=helpers.methods -local builtin=helpers.builtin -local extraluapaths={} -local extralibpaths={} -local luapaths=nil -local libpaths=nil -local oldluapath=nil -local oldlibpath=nil -local nofextralua=-1 -local nofextralib=-1 -local nofpathlua=-1 -local nofpathlib=-1 -local function listpaths(what,paths) - local nofpaths=#paths - if nofpaths>0 then - for i=1,nofpaths do - helpers.report("using %s path %i: %s",what,i,paths[i]) - end - else - helpers.report("no %s paths defined",what) - end - return nofpaths -end -local function getextraluapaths() - if helpers.trace and #extraluapaths~=nofextralua then - nofextralua=listpaths("extra lua",extraluapaths) - end - return extraluapaths -end -local function getextralibpaths() - if helpers.trace and #extralibpaths~=nofextralib then - nofextralib=listpaths("extra lib",extralibpaths) - end - return extralibpaths -end -local function getluapaths() - local luapath=package.path or "" - if oldluapath~=luapath then - luapaths=file.splitpath(luapath,";") - oldluapath=luapath - nofpathlua=-1 - end - if helpers.trace and #luapaths~=nofpathlua then - nofpathlua=listpaths("builtin lua",luapaths) - end - return luapaths -end -local function getlibpaths() - local libpath=package.cpath or "" - if oldlibpath~=libpath then - libpaths=file.splitpath(libpath,";") - oldlibpath=libpath - nofpathlib=-1 - end - if helpers.trace and #libpaths~=nofpathlib then - nofpathlib=listpaths("builtin lib",libpaths) - end - return libpaths -end -package.luapaths=getluapaths -package.libpaths=getlibpaths -package.extraluapaths=getextraluapaths -package.extralibpaths=getextralibpaths -local hashes={ - lua={}, - lib={}, -} -local function registerpath(tag,what,target,...) - local pathlist={... } - local cleanpath=helpers.cleanpath - local trace=helpers.trace - local report=helpers.report - local hash=hashes[what] - local function add(path) - local path=cleanpath(path) - if not hash[path] then - target[#target+1]=path - hash[path]=true - if trace then - report("registered %s path %s: %s",tag,#target,path) - end - else - if trace then - report("duplicate %s path: %s",tag,path) - end - end - end - for p=1,#pathlist do - local path=pathlist[p] - if type(path)=="table" then - for i=1,#path do - add(path[i]) - end - else - add(path) - end - end - return paths -end -helpers.registerpath=registerpath -function package.extraluapath(...) - registerpath("extra lua","lua",extraluapaths,...) -end -function package.extralibpath(...) - registerpath("extra lib","lib",extralibpaths,...) -end -local function loadedaslib(resolved,rawname) - local base=gsub(rawname,"%.","_") - local init="luaopen_"..gsub(base,"%.","_") - if helpers.trace then - helpers.report("calling loadlib with '%s' with init '%s'",resolved,init) - end - return package.loadlib(resolved,init) -end -helpers.loadedaslib=loadedaslib -local function loadedbypath(name,rawname,paths,islib,what) - local trace=helpers.trace - for p=1,#paths do - local path=paths[p] - local resolved=filejoin(path,name) - if trace then - helpers.report("%s path, identifying '%s' on '%s'",what,name,path) - end - if isreadable(resolved) then - if trace then - helpers.report("%s path, '%s' found on '%s'",what,name,resolved) - end - if islib then - return loadedaslib(resolved,rawname) - else - return loadfile(resolved) - end - end - end -end -helpers.loadedbypath=loadedbypath -local function loadedbyname(name,rawname) - if find(name,"^/") or find(name,"^[a-zA-Z]:/") then - local trace=helpers.trace - if trace then - helpers.report("qualified name, identifying '%s'",what,name) - end - if isreadable(name) then - if trace then - helpers.report("qualified name, '%s' found",what,name) - end - return loadfile(name) - end - end -end -helpers.loadedbyname=loadedbyname -methods["already loaded"]=function(name) - return package.loaded[name] -end -methods["preload table"]=function(name) - return builtin["preload table"](name) -end -methods["qualified path"]=function(name) - return loadedbyname(addsuffix(lualibfile(name),"lua"),name) -end -methods["lua extra list"]=function(name) - return loadedbypath(addsuffix(lualibfile(name),"lua"),name,getextraluapaths(),false,"lua") -end -methods["lib extra list"]=function(name) - return loadedbypath(addsuffix(lualibfile(name),os.libsuffix),name,getextralibpaths(),true,"lib") -end -methods["path specification"]=function(name) - getluapaths() - return builtin["path specification"](name) -end -methods["cpath specification"]=function(name) - getlibpaths() - return builtin["cpath specification"](name) -end -methods["all in one fallback"]=function(name) - return builtin["all in one fallback"](name) -end -methods["not loaded"]=function(name) - if helpers.trace then - helpers.report("unable to locate '%s'",name or "?") - end - return nil -end -local level=0 -local used={} -helpers.traceused=false -function helpers.loaded(name) - local sequence=helpers.sequence - level=level+1 - for i=1,#sequence do - local method=sequence[i] - if helpers.trace then - helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name) - end - local result,rest=methods[method](name) - if type(result)=="function" then - if helpers.trace then - helpers.report("%s, level '%s', method '%s', name '%s'","found",level,method,name) - end - if helpers.traceused then - used[#used+1]={ level=level,name=name } - end - level=level-1 - return result,rest - end - end - level=level-1 - return nil -end -function helpers.showused() - local n=#used - if n>0 then - helpers.report("%s libraries loaded:",n) - helpers.report() - for i=1,n do - local u=used[i] - helpers.report("%i %a",u.level,u.name) - end - helpers.report() - end -end -function helpers.unload(name) - if helpers.trace then - if package.loaded[name] then - helpers.report("unloading, name '%s', %s",name,"done") - else - helpers.report("unloading, name '%s', %s",name,"not loaded") - end - end - package.loaded[name]=nil -end -table.insert(searchers,1,helpers.loaded) - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true - --- original size: 29808, stripped down to: 16182 - -if not modules then modules={} end modules ['l-lpeg']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -lpeg=require("lpeg") -if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end -local type,next,tostring=type,next,tostring -local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format -local floor=math.floor -local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt -local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print -if setinspector then - setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) -end -lpeg.patterns=lpeg.patterns or {} -local patterns=lpeg.patterns -local anything=P(1) -local endofstring=P(-1) -local alwaysmatched=P(true) -patterns.anything=anything -patterns.endofstring=endofstring -patterns.beginofstring=alwaysmatched -patterns.alwaysmatched=alwaysmatched -local sign=S('+-') -local zero=P('0') -local digit=R('09') -local octdigit=R("07") -local lowercase=R("az") -local uppercase=R("AZ") -local underscore=P("_") -local hexdigit=digit+lowercase+uppercase -local cr,lf,crlf=P("\r"),P("\n"),P("\r\n") -local newline=crlf+S("\r\n") -local escaped=P("\\")*anything -local squote=P("'") -local dquote=P('"') -local space=P(" ") -local period=P(".") -local comma=P(",") -local utfbom_32_be=P('\000\000\254\255') -local utfbom_32_le=P('\255\254\000\000') -local utfbom_16_be=P('\254\255') -local utfbom_16_le=P('\255\254') -local utfbom_8=P('\239\187\191') -local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8 -local utftype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")+alwaysmatched*Cc("utf-8") -local utfstricttype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8") -local utfoffset=utfbom_32_be*Cc(4)+utfbom_32_le*Cc(4)+utfbom_16_be*Cc(2)+utfbom_16_le*Cc(2)+utfbom_8*Cc(3)+Cc(0) -local utf8next=R("\128\191") -patterns.utfbom_32_be=utfbom_32_be -patterns.utfbom_32_le=utfbom_32_le -patterns.utfbom_16_be=utfbom_16_be -patterns.utfbom_16_le=utfbom_16_le -patterns.utfbom_8=utfbom_8 -patterns.utf_16_be_nl=P("\000\r\000\n")+P("\000\r")+P("\000\n") -patterns.utf_16_le_nl=P("\r\000\n\000")+P("\r\000")+P("\n\000") -patterns.utf8one=R("\000\127") -patterns.utf8two=R("\194\223")*utf8next -patterns.utf8three=R("\224\239")*utf8next*utf8next -patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next -patterns.utfbom=utfbom -patterns.utftype=utftype -patterns.utfstricttype=utfstricttype -patterns.utfoffset=utfoffset -local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four -local validutf8char=utf8char^0*endofstring*Cc(true)+Cc(false) -local utf8character=P(1)*R("\128\191")^0 -patterns.utf8=utf8char -patterns.utf8char=utf8char -patterns.utf8character=utf8character -patterns.validutf8=validutf8char -patterns.validutf8char=validutf8char -local eol=S("\n\r") -local spacer=S(" \t\f\v") -local whitespace=eol+spacer -local nonspacer=1-spacer -local nonwhitespace=1-whitespace -patterns.eol=eol -patterns.spacer=spacer -patterns.whitespace=whitespace -patterns.nonspacer=nonspacer -patterns.nonwhitespace=nonwhitespace -local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) -local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0) -local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0)) -patterns.stripper=stripper -patterns.fullstripper=fullstripper -patterns.collapser=collapser -patterns.lowercase=lowercase -patterns.uppercase=uppercase -patterns.letter=patterns.lowercase+patterns.uppercase -patterns.space=space -patterns.tab=P("\t") -patterns.spaceortab=patterns.space+patterns.tab -patterns.newline=newline -patterns.emptyline=newline^1 -patterns.equal=P("=") -patterns.comma=comma -patterns.commaspacer=comma*spacer^0 -patterns.period=period -patterns.colon=P(":") -patterns.semicolon=P(";") -patterns.underscore=underscore -patterns.escaped=escaped -patterns.squote=squote -patterns.dquote=dquote -patterns.nosquote=(escaped+(1-squote))^0 -patterns.nodquote=(escaped+(1-dquote))^0 -patterns.unsingle=(squote/"")*patterns.nosquote*(squote/"") -patterns.undouble=(dquote/"")*patterns.nodquote*(dquote/"") -patterns.unquoted=patterns.undouble+patterns.unsingle -patterns.unspacer=((patterns.spacer^1)/"")^0 -patterns.singlequoted=squote*patterns.nosquote*squote -patterns.doublequoted=dquote*patterns.nodquote*dquote -patterns.quoted=patterns.doublequoted+patterns.singlequoted -patterns.digit=digit -patterns.octdigit=octdigit -patterns.hexdigit=hexdigit -patterns.sign=sign -patterns.cardinal=digit^1 -patterns.integer=sign^-1*digit^1 -patterns.unsigned=digit^0*period*digit^1 -patterns.float=sign^-1*patterns.unsigned -patterns.cunsigned=digit^0*comma*digit^1 -patterns.cfloat=sign^-1*patterns.cunsigned -patterns.number=patterns.float+patterns.integer -patterns.cnumber=patterns.cfloat+patterns.integer -patterns.oct=zero*octdigit^1 -patterns.octal=patterns.oct -patterns.HEX=zero*P("X")*(digit+uppercase)^1 -patterns.hex=zero*P("x")*(digit+lowercase)^1 -patterns.hexadecimal=zero*S("xX")*hexdigit^1 -patterns.hexafloat=sign^-1*zero*S("xX")*(hexdigit^0*period*hexdigit^1+hexdigit^1*period*hexdigit^0+hexdigit^1)*(S("pP")*sign^-1*hexdigit^1)^-1 -patterns.decafloat=sign^-1*(digit^0*period*digit^1+digit^1*period*digit^0+digit^1)*S("eE")*sign^-1*digit^1 -patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+underscore+digit)^0*endofstring -patterns.somecontent=(anything-newline-space)^1 -patterns.beginline=#(1-newline) -patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(P(-1)+Cc(" ")))^0)) -local function anywhere(pattern) - return P { P(pattern)+1*V(1) } -end -lpeg.anywhere=anywhere -function lpeg.instringchecker(p) - p=anywhere(p) - return function(str) - return lpegmatch(p,str) and true or false - end -end -function lpeg.splitter(pattern,action) - return (((1-P(pattern))^1)/action+1)^0 -end -function lpeg.tsplitter(pattern,action) - return Ct((((1-P(pattern))^1)/action+1)^0) -end -local splitters_s,splitters_m,splitters_t={},{},{} -local function splitat(separator,single) - local splitter=(single and splitters_s[separator]) or splitters_m[separator] - if not splitter then - separator=P(separator) - local other=C((1-separator)^0) - if single then - local any=anything - splitter=other*(separator*C(any^0)+"") - splitters_s[separator]=splitter - else - splitter=other*(separator*other)^0 - splitters_m[separator]=splitter - end - end - return splitter -end -local function tsplitat(separator) - local splitter=splitters_t[separator] - if not splitter then - splitter=Ct(splitat(separator)) - splitters_t[separator]=splitter - end - return splitter -end -lpeg.splitat=splitat -lpeg.tsplitat=tsplitat -function string.splitup(str,separator) - if not separator then - separator="," - end - return lpegmatch(splitters_m[separator] or splitat(separator),str) -end -local cache={} -function lpeg.split(separator,str) - local c=cache[separator] - if not c then - c=tsplitat(separator) - cache[separator]=c - end - return lpegmatch(c,str) -end -function string.split(str,separator) - if separator then - local c=cache[separator] - if not c then - c=tsplitat(separator) - cache[separator]=c - end - return lpegmatch(c,str) - else - return { str } - end -end -local spacing=patterns.spacer^0*newline -local empty=spacing*Cc("") -local nonempty=Cs((1-spacing)^1)*spacing^-1 -local content=(empty+nonempty)^1 -patterns.textline=content -local linesplitter=tsplitat(newline) -patterns.linesplitter=linesplitter -function string.splitlines(str) - return lpegmatch(linesplitter,str) -end -local cache={} -function lpeg.checkedsplit(separator,str) - local c=cache[separator] - if not c then - separator=P(separator) - local other=C((1-separator)^1) - c=Ct(separator^0*other*(separator^1*other)^0) - cache[separator]=c - end - return lpegmatch(c,str) -end -function string.checkedsplit(str,separator) - local c=cache[separator] - if not c then - separator=P(separator) - local other=C((1-separator)^1) - c=Ct(separator^0*other*(separator^1*other)^0) - cache[separator]=c - end - return lpegmatch(c,str) -end -local function f2(s) local c1,c2=byte(s,1,2) return c1*64+c2-12416 end -local function f3(s) local c1,c2,c3=byte(s,1,3) return (c1*64+c2)*64+c3-925824 end -local function f4(s) local c1,c2,c3,c4=byte(s,1,4) return ((c1*64+c2)*64+c3)*64+c4-63447168 end -local utf8byte=patterns.utf8one/byte+patterns.utf8two/f2+patterns.utf8three/f3+patterns.utf8four/f4 -patterns.utf8byte=utf8byte -local cache={} -function lpeg.stripper(str) - if type(str)=="string" then - local s=cache[str] - if not s then - s=Cs(((S(str)^1)/""+1)^0) - cache[str]=s - end - return s - else - return Cs(((str^1)/""+1)^0) - end -end -local cache={} -function lpeg.keeper(str) - if type(str)=="string" then - local s=cache[str] - if not s then - s=Cs((((1-S(str))^1)/""+1)^0) - cache[str]=s - end - return s - else - return Cs((((1-str)^1)/""+1)^0) - end -end -function lpeg.frontstripper(str) - return (P(str)+P(true))*Cs(anything^0) -end -function lpeg.endstripper(str) - return Cs((1-P(str)*endofstring)^0) -end -function lpeg.replacer(one,two,makefunction,isutf) - local pattern - local u=isutf and utf8char or 1 - if type(one)=="table" then - local no=#one - local p=P(false) - if no==0 then - for k,v in next,one do - p=p+P(k)/v - end - pattern=Cs((p+u)^0) - elseif no==1 then - local o=one[1] - one,two=P(o[1]),o[2] - pattern=Cs((one/two+u)^0) - else - for i=1,no do - local o=one[i] - p=p+P(o[1])/o[2] - end - pattern=Cs((p+u)^0) - end - else - pattern=Cs((P(one)/(two or "")+u)^0) - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end -function lpeg.finder(lst,makefunction,isutf) - local pattern - if type(lst)=="table" then - pattern=P(false) - if #lst==0 then - for k,v in next,lst do - pattern=pattern+P(k) - end - else - for i=1,#lst do - pattern=pattern+P(lst[i]) - end - end - else - pattern=P(lst) - end - if isutf then - pattern=((utf8char or 1)-pattern)^0*pattern - else - pattern=(1-pattern)^0*pattern - end - if makefunction then - return function(str) - return lpegmatch(pattern,str) - end - else - return pattern - end -end -local splitters_f,splitters_s={},{} -function lpeg.firstofsplit(separator) - local splitter=splitters_f[separator] - if not splitter then - local pattern=P(separator) - splitter=C((1-pattern)^0) - splitters_f[separator]=splitter - end - return splitter -end -function lpeg.secondofsplit(separator) - local splitter=splitters_s[separator] - if not splitter then - local pattern=P(separator) - splitter=(1-pattern)^0*pattern*C(anything^0) - splitters_s[separator]=splitter - end - return splitter -end -local splitters_s,splitters_p={},{} -function lpeg.beforesuffix(separator) - local splitter=splitters_s[separator] - if not splitter then - local pattern=P(separator) - splitter=C((1-pattern)^0)*pattern*endofstring - splitters_s[separator]=splitter - end - return splitter -end -function lpeg.afterprefix(separator) - local splitter=splitters_p[separator] - if not splitter then - local pattern=P(separator) - splitter=pattern*C(anything^0) - splitters_p[separator]=splitter - end - return splitter -end -function lpeg.balancer(left,right) - left,right=P(left),P(right) - return P { left*((1-left-right)+V(1))^0*right } -end -local nany=utf8char/"" -function lpeg.counter(pattern) - pattern=Cs((P(pattern)/" "+nany)^0) - return function(str) - return #lpegmatch(pattern,str) - end -end -utf=utf or (unicode and unicode.utf8) or {} -local utfcharacters=utf and utf.characters or string.utfcharacters -local utfgmatch=utf and utf.gmatch -local utfchar=utf and utf.char -lpeg.UP=lpeg.P -if utfcharacters then - function lpeg.US(str) - local p=P(false) - for uc in utfcharacters(str) do - p=p+P(uc) - end - return p - end -elseif utfgmatch then - function lpeg.US(str) - local p=P(false) - for uc in utfgmatch(str,".") do - p=p+P(uc) - end - return p - end -else - function lpeg.US(str) - local p=P(false) - local f=function(uc) - p=p+P(uc) - end - lpegmatch((utf8char/f)^0,str) - return p - end -end -local range=utf8byte*utf8byte+Cc(false) -function lpeg.UR(str,more) - local first,last - if type(str)=="number" then - first=str - last=more or first - else - first,last=lpegmatch(range,str) - if not last then - return P(str) - end - end - if first==last then - return P(str) - elseif utfchar and (last-first<8) then - local p=P(false) - for i=first,last do - p=p+P(utfchar(i)) - end - return p - else - local f=function(b) - return b>=first and b<=last - end - return utf8byte/f - end -end -function lpeg.is_lpeg(p) - return p and lpegtype(p)=="pattern" -end -function lpeg.oneof(list,...) - if type(list)~="table" then - list={ list,... } - end - local p=P(list[1]) - for l=2,#list do - p=p+P(list[l]) - end - return p -end -local sort=table.sort -local function copyindexed(old) - local new={} - for i=1,#old do - new[i]=old - end - return new -end -local function sortedkeys(tab) - local keys,s={},0 - for key,_ in next,tab do - s=s+1 - keys[s]=key - end - sort(keys) - return keys -end -function lpeg.append(list,pp,delayed,checked) - local p=pp - if #list>0 then - local keys=copyindexed(list) - sort(keys) - for i=#keys,1,-1 do - local k=keys[i] - if p then - p=P(k)+p - else - p=P(k) - end - end - elseif delayed then - local keys=sortedkeys(list) - if p then - for i=1,#keys,1 do - local k=keys[i] - local v=list[k] - p=P(k)/list+p - end - else - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - p=P(k)+p - else - p=P(k) - end - end - if p then - p=p/list - end - end - elseif checked then - local keys=sortedkeys(list) - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - if k==v then - p=P(k)+p - else - p=P(k)/v+p - end - else - if k==v then - p=P(k) - else - p=P(k)/v - end - end - end - else - local keys=sortedkeys(list) - for i=1,#keys do - local k=keys[i] - local v=list[k] - if p then - p=P(k)/v+p - else - p=P(k)/v - end - end - end - return p -end -local function make(t) - local p - local keys=sortedkeys(t) - for i=1,#keys do - local k=keys[i] - local v=t[k] - if not p then - if next(v) then - p=P(k)*make(v) - else - p=P(k) - end - else - if next(v) then - p=p+P(k)*make(v) - else - p=p+P(k) - end - end - end - return p -end -function lpeg.utfchartabletopattern(list) - local tree={} - for i=1,#list do - local t=tree - for c in gmatch(list[i],".") do - if not t[c] then - t[c]={} - end - t=t[c] - end - end - return make(tree) -end -patterns.containseol=lpeg.finder(eol) -local function nextstep(n,step,result) - local m=n%step - local d=floor(n/step) - if d>0 then - local v=V(tostring(step)) - local s=result.start - for i=1,d do - if s then - s=v*s - else - s=v - end - end - result.start=s - end - if step>1 and result.start then - local v=V(tostring(step/2)) - result[tostring(step)]=v*v - end - if step>0 then - return nextstep(m,step/2,result) - else - return result - end -end -function lpeg.times(pattern,n) - return P(nextstep(n,2^16,{ "start",["1"]=pattern })) -end -local trailingzeros=zero^0*-digit -local case_1=period*trailingzeros/"" -local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"") -local number=digit^1*(case_1+case_2) -local stripper=Cs((number+1)^0) -lpeg.patterns.stripzeros=stripper - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-function"] = package.loaded["l-function"] or true - --- original size: 361, stripped down to: 322 - -if not modules then modules={} end modules ['l-functions']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -functions=functions or {} -function functions.dummy() end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-string"] = package.loaded["l-string"] or true - --- original size: 5671, stripped down to: 2827 - -if not modules then modules={} end modules ['l-string']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local string=string -local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs -local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote -function string.unquoted(str) - return lpegmatch(unquoted,str) or str -end -function string.quoted(str) - return format("%q",str) -end -function string.count(str,pattern) - local n=0 - for _ in gmatch(str,pattern) do - n=n+1 - end - return n -end -function string.limit(str,n,sentinel) - if #str>n then - sentinel=sentinel or "..." - return sub(str,1,(n-#sentinel))..sentinel - else - return str - end -end -local stripper=patterns.stripper -local fullstripper=patterns.fullstripper -local collapser=patterns.collapser -local longtostring=patterns.longtostring -function string.strip(str) - return lpegmatch(stripper,str) or "" -end -function string.fullstrip(str) - return lpegmatch(fullstripper,str) or "" -end -function string.collapsespaces(str) - return lpegmatch(collapser,str) or "" -end -function string.longtostring(str) - return lpegmatch(longtostring,str) or "" -end -local pattern=P(" ")^0*P(-1) -function string.is_empty(str) - if str=="" then - return true - else - return lpegmatch(pattern,str) and true or false - end -end -local anything=patterns.anything -local allescapes=Cc("%")*S(".-+%?()[]*") -local someescapes=Cc("%")*S(".-+%()[]") -local matchescapes=Cc(".")*S("*?") -local pattern_a=Cs ((allescapes+anything )^0 ) -local pattern_b=Cs ((someescapes+matchescapes+anything )^0 ) -local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") ) -function string.escapedpattern(str,simple) - return lpegmatch(simple and pattern_b or pattern_a,str) -end -function string.topattern(str,lowercase,strict) - if str=="" or type(str)~="string" then - return ".*" - elseif strict then - str=lpegmatch(pattern_c,str) - else - str=lpegmatch(pattern_b,str) - end - if lowercase then - return lower(str) - else - return str - end -end -function string.valid(str,default) - return (type(str)=="string" and str~="" and str) or default or nil -end -string.itself=function(s) return s end -local pattern=Ct(C(1)^0) -function string.totable(str) - return lpegmatch(pattern,str) -end -local replacer=lpeg.replacer("@","%%") -function string.tformat(fmt,...) - return format(lpegmatch(replacer,fmt),...) -end -string.quote=string.quoted -string.unquote=string.unquoted - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-table"] = package.loaded["l-table"] or true - --- original size: 31142, stripped down to: 20283 - -if not modules then modules={} end modules ['l-table']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select -local table,string=table,string -local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove -local format,lower,dump=string.format,string.lower,string.dump -local getmetatable,setmetatable=getmetatable,setmetatable -local getinfo=debug.getinfo -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local floor=math.floor -local stripper=patterns.stripper -function table.strip(tab) - local lst,l={},0 - for i=1,#tab do - local s=lpegmatch(stripper,tab[i]) or "" - if s=="" then - else - l=l+1 - lst[l]=s - end - end - return lst -end -function table.keys(t) - if t then - local keys,k={},0 - for key,_ in next,t do - k=k+1 - keys[k]=key - end - return keys - else - return {} - end -end -local function compare(a,b) - local ta,tb=type(a),type(b) - if ta==tb then - return a<b - else - return tostring(a)<tostring(b) - end -end -local function sortedkeys(tab) - if tab then - local srt,category,s={},0,0 - for key,_ in next,tab do - s=s+1 - srt[s]=key - if category==3 then - else - local tkey=type(key) - if tkey=="string" then - category=(category==2 and 3) or 1 - elseif tkey=="number" then - category=(category==1 and 3) or 2 - else - category=3 - end - end - end - if category==0 or category==3 then - sort(srt,compare) - else - sort(srt) - end - return srt - else - return {} - end -end -local function sortedhashkeys(tab,cmp) - if tab then - local srt,s={},0 - for key,_ in next,tab do - if key then - s=s+1 - srt[s]=key - end - end - sort(srt,cmp) - return srt - else - return {} - end -end -function table.allkeys(t) - local keys={} - for k,v in next,t do - for k,v in next,v do - keys[k]=true - end - end - return sortedkeys(keys) -end -table.sortedkeys=sortedkeys -table.sortedhashkeys=sortedhashkeys -local function nothing() end -local function sortedhash(t,cmp) - if t then - local s - if cmp then - s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end) - else - s=sortedkeys(t) - end - local n=0 - local m=#s - local function kv(s) - if n<m then - n=n+1 - local k=s[n] - return k,t[k] - end - end - return kv,s - else - return nothing - end -end -table.sortedhash=sortedhash -table.sortedpairs=sortedhash -function table.append(t,list) - local n=#t - for i=1,#list do - n=n+1 - t[n]=list[i] - end - return t -end -function table.prepend(t,list) - local nl=#list - local nt=nl+#t - for i=#t,1,-1 do - t[nt]=t[i] - nt=nt-1 - end - for i=1,#list do - t[i]=list[i] - end - return t -end -function table.merge(t,...) - t=t or {} - for i=1,select("#",...) do - for k,v in next,(select(i,...)) do - t[k]=v - end - end - return t -end -function table.merged(...) - local t={} - for i=1,select("#",...) do - for k,v in next,(select(i,...)) do - t[k]=v - end - end - return t -end -function table.imerge(t,...) - local nt=#t - for i=1,select("#",...) do - local nst=select(i,...) - for j=1,#nst do - nt=nt+1 - t[nt]=nst[j] - end - end - return t -end -function table.imerged(...) - local tmp,ntmp={},0 - for i=1,select("#",...) do - local nst=select(i,...) - for j=1,#nst do - ntmp=ntmp+1 - tmp[ntmp]=nst[j] - end - end - return tmp -end -local function fastcopy(old,metatabletoo) - if old then - local new={} - for k,v in next,old do - if type(v)=="table" then - new[k]=fastcopy(v,metatabletoo) - else - new[k]=v - end - end - if metatabletoo then - local mt=getmetatable(old) - if mt then - setmetatable(new,mt) - end - end - return new - else - return {} - end -end -local function copy(t,tables) - tables=tables or {} - local tcopy={} - if not tables[t] then - tables[t]=tcopy - end - for i,v in next,t do - if type(i)=="table" then - if tables[i] then - i=tables[i] - else - i=copy(i,tables) - end - end - if type(v)~="table" then - tcopy[i]=v - elseif tables[v] then - tcopy[i]=tables[v] - else - tcopy[i]=copy(v,tables) - end - end - local mt=getmetatable(t) - if mt then - setmetatable(tcopy,mt) - end - return tcopy -end -table.fastcopy=fastcopy -table.copy=copy -function table.derive(parent) - local child={} - if parent then - setmetatable(child,{ __index=parent }) - end - return child -end -function table.tohash(t,value) - local h={} - if t then - if value==nil then value=true end - for _,v in next,t do - h[v]=value - end - end - return h -end -function table.fromhash(t) - local hsh,h={},0 - for k,v in next,t do - if v then - h=h+1 - hsh[h]=k - end - end - return hsh -end -local noquotes,hexify,handle,reduce,compact,inline,functions -local reserved=table.tohash { - 'and','break','do','else','elseif','end','false','for','function','if', - 'in','local','nil','not','or','repeat','return','then','true','until','while', - 'NaN','goto', -} -local function simple_table(t) - if #t>0 then - local n=0 - for _,v in next,t do - n=n+1 - end - if n==#t then - local tt,nt={},0 - for i=1,#t do - local v=t[i] - local tv=type(v) - if tv=="number" then - nt=nt+1 - if hexify then - tt[nt]=format("0x%04X",v) - else - tt[nt]=tostring(v) - end - elseif tv=="string" then - nt=nt+1 - tt[nt]=format("%q",v) - elseif tv=="boolean" then - nt=nt+1 - tt[nt]=v and "true" or "false" - else - tt=nil - break - end - end - return tt - end - end - return nil -end -local propername=patterns.propername -local function dummy() end -local function do_serialize(root,name,depth,level,indexed) - if level>0 then - depth=depth.." " - if indexed then - handle(format("%s{",depth)) - else - local tn=type(name) - if tn=="number" then - if hexify then - handle(format("%s[0x%04X]={",depth,name)) - else - handle(format("%s[%s]={",depth,name)) - end - elseif tn=="string" then - if noquotes and not reserved[name] and lpegmatch(propername,name) then - handle(format("%s%s={",depth,name)) - else - handle(format("%s[%q]={",depth,name)) - end - elseif tn=="boolean" then - handle(format("%s[%s]={",depth,name and "true" or "false")) - else - handle(format("%s{",depth)) - end - end - end - if root and next(root) then - local first,last=nil,0 - if compact then - last=#root - for k=1,last do - if root[k]==nil then - last=k-1 - break - end - end - if last>0 then - first=1 - end - end - local sk=sortedkeys(root) - for i=1,#sk do - local k=sk[i] - local v=root[k] - local tv,tk=type(v),type(k) - if compact and first and tk=="number" and k>=first and k<=last then - if tv=="number" then - if hexify then - handle(format("%s 0x%04X,",depth,v)) - else - handle(format("%s %s,",depth,v)) - end - elseif tv=="string" then - if reduce and tonumber(v) then - handle(format("%s %s,",depth,v)) - else - handle(format("%s %q,",depth,v)) - end - elseif tv=="table" then - if not next(v) then - handle(format("%s {},",depth)) - elseif inline then - local st=simple_table(v) - if st then - handle(format("%s { %s },",depth,concat(st,", "))) - else - do_serialize(v,k,depth,level+1,true) - end - else - do_serialize(v,k,depth,level+1,true) - end - elseif tv=="boolean" then - handle(format("%s %s,",depth,v and "true" or "false")) - elseif tv=="function" then - if functions then - handle(format('%s load(%q),',depth,dump(v))) - else - handle(format('%s "function",',depth)) - end - else - handle(format("%s %q,",depth,tostring(v))) - end - elseif k=="__p__" then - if false then - handle(format("%s __p__=nil,",depth)) - end - elseif tv=="number" then - if tk=="number" then - if hexify then - handle(format("%s [0x%04X]=0x%04X,",depth,k,v)) - else - handle(format("%s [%s]=%s,",depth,k,v)) - end - elseif tk=="boolean" then - if hexify then - handle(format("%s [%s]=0x%04X,",depth,k and "true" or "false",v)) - else - handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) - end - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - if hexify then - handle(format("%s %s=0x%04X,",depth,k,v)) - else - handle(format("%s %s=%s,",depth,k,v)) - end - else - if hexify then - handle(format("%s [%q]=0x%04X,",depth,k,v)) - else - handle(format("%s [%q]=%s,",depth,k,v)) - end - end - elseif tv=="string" then - if reduce and tonumber(v) then - if tk=="number" then - if hexify then - handle(format("%s [0x%04X]=%s,",depth,k,v)) - else - handle(format("%s [%s]=%s,",depth,k,v)) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,v)) - else - handle(format("%s [%q]=%s,",depth,k,v)) - end - else - if tk=="number" then - if hexify then - handle(format("%s [0x%04X]=%q,",depth,k,v)) - else - handle(format("%s [%s]=%q,",depth,k,v)) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,v)) - else - handle(format("%s [%q]=%q,",depth,k,v)) - end - end - elseif tv=="table" then - if not next(v) then - if tk=="number" then - if hexify then - handle(format("%s [0x%04X]={},",depth,k)) - else - handle(format("%s [%s]={},",depth,k)) - end - elseif tk=="boolean" then - handle(format("%s [%s]={},",depth,k and "true" or "false")) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={},",depth,k)) - else - handle(format("%s [%q]={},",depth,k)) - end - elseif inline then - local st=simple_table(v) - if st then - if tk=="number" then - if hexify then - handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%s]={ %s },",depth,k,concat(st,", "))) - end - elseif tk=="boolean" then - handle(format("%s [%s]={ %s },",depth,k and "true" or "false",concat(st,", "))) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s={ %s },",depth,k,concat(st,", "))) - else - handle(format("%s [%q]={ %s },",depth,k,concat(st,", "))) - end - else - do_serialize(v,k,depth,level+1) - end - else - do_serialize(v,k,depth,level+1) - end - elseif tv=="boolean" then - if tk=="number" then - if hexify then - handle(format("%s [0x%04X]=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false")) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) - end - elseif tv=="function" then - if functions then - local f=getinfo(v).what=="C" and dump(dummy) or dump(v) - if tk=="number" then - if hexify then - handle(format("%s [0x%04X]=load(%q),",depth,k,f)) - else - handle(format("%s [%s]=load(%q),",depth,k,f)) - end - elseif tk=="boolean" then - handle(format("%s [%s]=load(%q),",depth,k and "true" or "false",f)) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=load(%q),",depth,k,f)) - else - handle(format("%s [%q]=load(%q),",depth,k,f)) - end - end - else - if tk=="number" then - if hexify then - handle(format("%s [0x%04X]=%q,",depth,k,tostring(v))) - else - handle(format("%s [%s]=%q,",depth,k,tostring(v))) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",tostring(v))) - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%q,",depth,k,tostring(v))) - else - handle(format("%s [%q]=%q,",depth,k,tostring(v))) - end - end - end - end - if level>0 then - handle(format("%s},",depth)) - end -end -local function serialize(_handle,root,name,specification) - local tname=type(name) - if type(specification)=="table" then - noquotes=specification.noquotes - hexify=specification.hexify - handle=_handle or specification.handle or print - reduce=specification.reduce or false - functions=specification.functions - compact=specification.compact - inline=specification.inline and compact - if functions==nil then - functions=true - end - if compact==nil then - compact=true - end - if inline==nil then - inline=compact - end - else - noquotes=false - hexify=false - handle=_handle or print - reduce=false - compact=true - inline=true - functions=true - end - if tname=="string" then - if name=="return" then - handle("return {") - else - handle(name.."={") - end - elseif tname=="number" then - if hexify then - handle(format("[0x%04X]={",name)) - else - handle("["..name.."]={") - end - elseif tname=="boolean" then - if name then - handle("return {") - else - handle("{") - end - else - handle("t={") - end - if root then - if getmetatable(root) then - local dummy=root._w_h_a_t_e_v_e_r_ - root._w_h_a_t_e_v_e_r_=nil - end - if next(root) then - do_serialize(root,name,"",0) - end - end - handle("}") -end -function table.serialize(root,name,specification) - local t,n={},0 - local function flush(s) - n=n+1 - t[n]=s - end - serialize(flush,root,name,specification) - return concat(t,"\n") -end -table.tohandle=serialize -local maxtab=2*1024 -function table.tofile(filename,root,name,specification) - local f=io.open(filename,'w') - if f then - if maxtab>1 then - local t,n={},0 - local function flush(s) - n=n+1 - t[n]=s - if n>maxtab then - f:write(concat(t,"\n"),"\n") - t,n={},0 - end - end - serialize(flush,root,name,specification) - f:write(concat(t,"\n"),"\n") - else - local function flush(s) - f:write(s,"\n") - end - serialize(flush,root,name,specification) - end - f:close() - io.flush() - end -end -local function flattened(t,f,depth) - if f==nil then - f={} - depth=0xFFFF - elseif tonumber(f) then - depth=f - f={} - elseif not depth then - depth=0xFFFF - end - for k,v in next,t do - if type(k)~="number" then - if depth>0 and type(v)=="table" then - flattened(v,f,depth-1) - else - f[#f+1]=v - end - end - end - for k=1,#t do - local v=t[k] - if depth>0 and type(v)=="table" then - flattened(v,f,depth-1) - else - f[#f+1]=v - end - end - return f -end -table.flattened=flattened -local function unnest(t,f) - if not f then - f={} - end - for i=1,#t do - local v=t[i] - if type(v)=="table" then - if type(v[1])=="table" then - unnest(v,f) - else - f[#f+1]=v - end - else - f[#f+1]=v - end - end - return f -end -function table.unnest(t) - return unnest(t) -end -local function are_equal(a,b,n,m) - if a and b and #a==#b then - n=n or 1 - m=m or #a - for i=n,m do - local ai,bi=a[i],b[i] - if ai==bi then - elseif type(ai)=="table" and type(bi)=="table" then - if not are_equal(ai,bi) then - return false - end - else - return false - end - end - return true - else - return false - end -end -local function identical(a,b) - for ka,va in next,a do - local vb=b[ka] - if va==vb then - elseif type(va)=="table" and type(vb)=="table" then - if not identical(va,vb) then - return false - end - else - return false - end - end - return true -end -table.identical=identical -table.are_equal=are_equal -function table.compact(t) - if t then - for k,v in next,t do - if not next(v) then - t[k]=nil - end - end - end -end -function table.contains(t,v) - if t then - for i=1,#t do - if t[i]==v then - return i - end - end - end - return false -end -function table.count(t) - local n=0 - for k,v in next,t do - n=n+1 - end - return n -end -function table.swapped(t,s) - local n={} - if s then - for k,v in next,s do - n[k]=v - end - end - for k,v in next,t do - n[v]=k - end - return n -end -function table.mirrored(t) - local n={} - for k,v in next,t do - n[v]=k - n[k]=v - end - return n -end -function table.reversed(t) - if t then - local tt,tn={},#t - if tn>0 then - local ttn=0 - for i=tn,1,-1 do - ttn=ttn+1 - tt[ttn]=t[i] - end - end - return tt - end -end -function table.reverse(t) - if t then - local n=#t - for i=1,floor(n/2) do - local j=n-i+1 - t[i],t[j]=t[j],t[i] - end - return t - end -end -function table.sequenced(t,sep,simple) - if not t then - return "" - end - local n=#t - local s={} - if n>0 then - for i=1,n do - s[i]=tostring(t[i]) - end - else - n=0 - for k,v in sortedhash(t) do - if simple then - if v==true then - n=n+1 - s[n]=k - elseif v and v~="" then - n=n+1 - s[n]=k.."="..tostring(v) - end - else - n=n+1 - s[n]=k.."="..tostring(v) - end - end - end - return concat(s,sep or " | ") -end -function table.print(t,...) - if type(t)~="table" then - print(tostring(t)) - else - serialize(print,t,...) - end -end -if setinspector then - setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) -end -function table.sub(t,i,j) - return { unpack(t,i,j) } -end -function table.is_empty(t) - return not t or not next(t) -end -function table.has_one_entry(t) - return t and not next(t,next(t)) -end -function table.loweredkeys(t) - local l={} - for k,v in next,t do - l[lower(k)]=v - end - return l -end -function table.unique(old) - local hash={} - local new={} - local n=0 - for i=1,#old do - local oi=old[i] - if not hash[oi] then - n=n+1 - new[n]=oi - hash[oi]=true - end - end - return new -end -function table.sorted(t,...) - sort(t,...) - return t -end -function table.values(t,s) - if t then - local values,keys,v={},{},0 - for key,value in next,t do - if not keys[value] then - v=v+1 - values[v]=value - keys[k]=key - end - end - if s then - sort(values) - end - return values - else - return {} - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-io"] = package.loaded["l-io"] or true - --- original size: 8817, stripped down to: 6340 - -if not modules then modules={} end modules ['l-io']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local io=io -local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format -local concat=table.concat -local floor=math.floor -local type=type -if string.find(os.getenv("PATH"),";") then - io.fileseparator,io.pathseparator="\\",";" -else - io.fileseparator,io.pathseparator="/",":" -end -local function readall(f) - return f:read("*all") -end -local function readall(f) - local size=f:seek("end") - if size==0 then - return "" - elseif size<1024*1024 then - f:seek("set",0) - return f:read('*all') - else - local done=f:seek("set",0) - local step - if size<1024*1024 then - step=1024*1024 - elseif size>16*1024*1024 then - step=16*1024*1024 - else - step=floor(size/(1024*1024))*1024*1024/8 - end - local data={} - while true do - local r=f:read(step) - if not r then - return concat(data) - else - data[#data+1]=r - end - end - end -end -io.readall=readall -function io.loaddata(filename,textmode) - local f=io.open(filename,(textmode and 'r') or 'rb') - if f then - local data=readall(f) - f:close() - if #data>0 then - return data - end - end -end -function io.savedata(filename,data,joiner) - local f=io.open(filename,"wb") - if f then - if type(data)=="table" then - f:write(concat(data,joiner or "")) - elseif type(data)=="function" then - data(f) - else - f:write(data or "") - end - f:close() - io.flush() - return true - else - return false - end -end -function io.loadlines(filename,n) - local f=io.open(filename,'r') - if not f then - elseif n then - local lines={} - for i=1,n do - local line=f:read("*lines") - if line then - lines[#lines+1]=line - else - break - end - end - f:close() - lines=concat(lines,"\n") - if #lines>0 then - return lines - end - else - local line=f:read("*line") or "" - f:close() - if #line>0 then - return line - end - end -end -function io.loadchunk(filename,n) - local f=io.open(filename,'rb') - if f then - local data=f:read(n or 1024) - f:close() - if #data>0 then - return data - end - end -end -function io.exists(filename) - local f=io.open(filename) - if f==nil then - return false - else - f:close() - return true - end -end -function io.size(filename) - local f=io.open(filename) - if f==nil then - return 0 - else - local s=f:seek("end") - f:close() - return s - end -end -function io.noflines(f) - if type(f)=="string" then - local f=io.open(filename) - if f then - local n=f and io.noflines(f) or 0 - f:close() - return n - else - return 0 - end - else - local n=0 - for _ in f:lines() do - n=n+1 - end - f:seek('set',0) - return n - end -end -local nextchar={ - [ 4]=function(f) - return f:read(1,1,1,1) - end, - [ 2]=function(f) - return f:read(1,1) - end, - [ 1]=function(f) - return f:read(1) - end, - [-2]=function(f) - local a,b=f:read(1,1) - return b,a - end, - [-4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - return d,c,b,a - end -} -function io.characters(f,n) - if f then - return nextchar[n or 1],f - end -end -local nextbyte={ - [4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - if d then - return byte(a),byte(b),byte(c),byte(d) - end - end, - [3]=function(f) - local a,b,c=f:read(1,1,1) - if b then - return byte(a),byte(b),byte(c) - end - end, - [2]=function(f) - local a,b=f:read(1,1) - if b then - return byte(a),byte(b) - end - end, - [1]=function (f) - local a=f:read(1) - if a then - return byte(a) - end - end, - [-2]=function (f) - local a,b=f:read(1,1) - if b then - return byte(b),byte(a) - end - end, - [-3]=function(f) - local a,b,c=f:read(1,1,1) - if b then - return byte(c),byte(b),byte(a) - end - end, - [-4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - if d then - return byte(d),byte(c),byte(b),byte(a) - end - end -} -function io.bytes(f,n) - if f then - return nextbyte[n or 1],f - else - return nil,nil - end -end -function io.ask(question,default,options) - while true do - io.write(question) - if options then - io.write(format(" [%s]",concat(options,"|"))) - end - if default then - io.write(format(" [%s]",default)) - end - io.write(format(" ")) - io.flush() - local answer=io.read() - answer=gsub(answer,"^%s*(.*)%s*$","%1") - if answer=="" and default then - return default - elseif not options then - return answer - else - for k=1,#options do - if options[k]==answer then - return answer - end - end - local pattern="^"..answer - for k=1,#options do - local v=options[k] - if find(v,pattern) then - return v - end - end - end - end -end -local function readnumber(f,n,m) - if m then - f:seek("set",n) - n=m - end - if n==1 then - return byte(f:read(1)) - elseif n==2 then - local a,b=byte(f:read(2),1,2) - return 256*a+b - elseif n==3 then - local a,b,c=byte(f:read(3),1,3) - return 256*256*a+256*b+c - elseif n==4 then - local a,b,c,d=byte(f:read(4),1,4) - return 256*256*256*a+256*256*b+256*c+d - elseif n==8 then - local a,b=readnumber(f,4),readnumber(f,4) - return 256*a+b - elseif n==12 then - local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4) - return 256*256*a+256*b+c - elseif n==-2 then - local b,a=byte(f:read(2),1,2) - return 256*a+b - elseif n==-3 then - local c,b,a=byte(f:read(3),1,3) - return 256*256*a+256*b+c - elseif n==-4 then - local d,c,b,a=byte(f:read(4),1,4) - return 256*256*256*a+256*256*b+256*c+d - elseif n==-8 then - local h,g,f,e,d,c,b,a=byte(f:read(8),1,8) - return 256*256*256*256*256*256*256*a+256*256*256*256*256*256*b+256*256*256*256*256*c+256*256*256*256*d+256*256*256*e+256*256*f+256*g+h - else - return 0 - end -end -io.readnumber=readnumber -function io.readstring(f,n,m) - if m then - f:seek("set",n) - n=m - end - local str=gsub(f:read(n),"\000","") - return str -end -if not io.i_limiter then function io.i_limiter() end end -if not io.o_limiter then function io.o_limiter() end end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-number"] = package.loaded["l-number"] or true - --- original size: 4939, stripped down to: 2830 - -if not modules then modules={} end modules ['l-number']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local tostring,tonumber=tostring,tonumber -local format,floor,match,rep=string.format,math.floor,string.match,string.rep -local concat,insert=table.concat,table.insert -local lpegmatch=lpeg.match -number=number or {} -local number=number -if bit32 then - local btest,bor=bit32.btest,bit32.bor - function number.bit(p) - return 2^(p-1) - end - number.hasbit=btest - number.setbit=bor - function number.setbit(x,p) - return btest(x,p) and x or x+p - end - function number.clearbit(x,p) - return btest(x,p) and x-p or x - end -else - function number.bit(p) - return 2^(p-1) - end - function number.hasbit(x,p) - return x%(p+p)>=p - end - function number.setbit(x,p) - return (x%(p+p)>=p) and x or x+p - end - function number.clearbit(x,p) - return (x%(p+p)>=p) and x-p or x - end -end -if bit32 then - local bextract=bit32.extract - local t={ - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - } - function number.tobitstring(b,m) - local n=32 - for i=0,31 do - local v=bextract(b,i) - local k=32-i - if v==1 then - n=k - t[k]="1" - else - t[k]="0" - end - end - if m then - m=33-m*8 - if m<1 then - m=1 - end - return concat(t,"",m) - elseif n<8 then - return concat(t) - elseif n<16 then - return concat(t,"",9) - elseif n<24 then - return concat(t,"",17) - else - return concat(t,"",25) - end - end -else - function number.tobitstring(n,m) - if n>0 then - local t={} - while n>0 do - insert(t,1,n%2>0 and 1 or 0) - n=floor(n/2) - end - local nn=8-#t%8 - if nn>0 and nn<8 then - for i=1,nn do - insert(t,1,0) - end - end - if m then - m=m*8-#t - if m>0 then - insert(t,1,rep("0",m)) - end - end - return concat(t) - elseif m then - rep("00000000",m) - else - return "00000000" - end - end -end -function number.valid(str,default) - return tonumber(str) or default or nil -end -function number.toevenhex(n) - local s=format("%X",n) - if #s%2==0 then - return s - else - return "0"..s - end -end -local one=lpeg.C(1-lpeg.S('')/tonumber)^1 -function number.toset(n) - return lpegmatch(one,tostring(n)) -end -local function bits(n,i,...) - if n>0 then - local m=n%2 - local n=floor(n/2) - if m>0 then - return bits(n,i+1,i,...) - else - return bits(n,i+1,...) - end - else - return... - end -end -function number.bits(n) - return { bits(n,1) } -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-set"] = package.loaded["l-set"] or true - --- original size: 1923, stripped down to: 1133 - -if not modules then modules={} end modules ['l-set']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -set=set or {} -local nums={} -local tabs={} -local concat=table.concat -local next,type=next,type -set.create=table.tohash -function set.tonumber(t) - if next(t) then - local s="" - for k,v in next,t do - if v then - s=s.." "..k - end - end - local n=nums[s] - if not n then - n=#tabs+1 - tabs[n]=t - nums[s]=n - end - return n - else - return 0 - end -end -function set.totable(n) - if n==0 then - return {} - else - return tabs[n] or {} - end -end -function set.tolist(n) - if n==0 or not tabs[n] then - return "" - else - local t,n={},0 - for k,v in next,tabs[n] do - if v then - n=n+1 - t[n]=k - end - end - return concat(t," ") - end -end -function set.contains(n,s) - if type(n)=="table" then - return n[s] - elseif n==0 then - return false - else - local t=tabs[n] - return t and t[s] - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-os"] = package.loaded["l-os"] or true - --- original size: 16023, stripped down to: 9634 - -if not modules then modules={} end modules ['l-os']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local os=os -local date,time=os.date,os.time -local find,format,gsub,upper,gmatch=string.find,string.format,string.gsub,string.upper,string.gmatch -local concat=table.concat -local random,ceil,randomseed=math.random,math.ceil,math.randomseed -local rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring=rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring -math.initialseed=tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6)) -randomseed(math.initialseed) -if not os.__getenv__ then - os.__getenv__=os.getenv - os.__setenv__=os.setenv - if os.env then - local osgetenv=os.getenv - local ossetenv=os.setenv - local osenv=os.env local _=osenv.PATH - function os.setenv(k,v) - if v==nil then - v="" - end - local K=upper(k) - osenv[K]=v - if type(v)=="table" then - v=concat(v,";") - end - ossetenv(K,v) - end - function os.getenv(k) - local K=upper(k) - local v=osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k) - if v=="" then - return nil - else - return v - end - end - else - local ossetenv=os.setenv - local osgetenv=os.getenv - local osenv={} - function os.setenv(k,v) - if v==nil then - v="" - end - local K=upper(k) - osenv[K]=v - end - function os.getenv(k) - local K=upper(k) - local v=osenv[K] or osgetenv(K) or osgetenv(k) - if v=="" then - return nil - else - return v - end - end - local function __index(t,k) - return os.getenv(k) - end - local function __newindex(t,k,v) - os.setenv(k,v) - end - os.env={} - setmetatable(os.env,{ __index=__index,__newindex=__newindex } ) - end -end -local execute,spawn,exec,iopopen,ioflush=os.execute,os.spawn or os.execute,os.exec or os.execute,io.popen,io.flush -function os.execute(...) ioflush() return execute(...) end -function os.spawn (...) ioflush() return spawn (...) end -function os.exec (...) ioflush() return exec (...) end -function io.popen (...) ioflush() return iopopen(...) end -function os.resultof(command) - local handle=io.popen(command,"r") - if handle then - local result=handle:read("*all") or "" - handle:close() - return result - else - return "" - end -end -if not io.fileseparator then - if find(os.getenv("PATH"),";") then - io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "mswin" - else - io.fileseparator,io.pathseparator,os.type="/",":",os.type or "unix" - end -end -os.type=os.type or (io.pathseparator==";" and "windows") or "unix" -os.name=os.name or (os.type=="windows" and "mswin" ) or "linux" -if os.type=="windows" then - os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' } -else - os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' } -end -local launchers={ - windows="start %s", - macosx="open %s", - unix="$BROWSER %s &> /dev/null &", -} -function os.launch(str) - os.execute(format(launchers[os.name] or launchers.unix,str)) -end -if not os.times then - function os.times() - return { - utime=os.gettimeofday(), - stime=0, - cutime=0, - cstime=0, - } - end -end -local gettimeofday=os.gettimeofday or os.clock -os.gettimeofday=gettimeofday -local startuptime=gettimeofday() -function os.runtime() - return gettimeofday()-startuptime -end -local resolvers=os.resolvers or {} -os.resolvers=resolvers -setmetatable(os,{ __index=function(t,k) - local r=resolvers[k] - return r and r(t,k) or nil -end }) -local name,platform=os.name or "linux",os.getenv("MTX_PLATFORM") or "" -local function guess() - local architecture=os.resultof("uname -m") or "" - if architecture~="" then - return architecture - end - architecture=os.getenv("HOSTTYPE") or "" - if architecture~="" then - return architecture - end - return os.resultof("echo $HOSTTYPE") or "" -end -if platform~="" then - os.platform=platform -elseif os.type=="windows" then - function resolvers.platform(t,k) - local platform,architecture="",os.getenv("PROCESSOR_ARCHITECTURE") or "" - if find(architecture,"AMD64") then - platform="win64" - else - platform="mswin" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="linux" then - function resolvers.platform(t,k) - local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" - if find(architecture,"x86_64") then - platform="linux-64" - elseif find(architecture,"ppc") then - platform="linux-ppc" - else - platform="linux" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="macosx" then - function resolvers.platform(t,k) - local platform,architecture="",os.resultof("echo $HOSTTYPE") or "" - if architecture=="" then - platform="osx-intel" - elseif find(architecture,"i386") then - platform="osx-intel" - elseif find(architecture,"x86_64") then - platform="osx-64" - else - platform="osx-ppc" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="sunos" then - function resolvers.platform(t,k) - local platform,architecture="",os.resultof("uname -m") or "" - if find(architecture,"sparc") then - platform="solaris-sparc" - else - platform="solaris-intel" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="freebsd" then - function resolvers.platform(t,k) - local platform,architecture="",os.resultof("uname -m") or "" - if find(architecture,"amd64") then - platform="freebsd-amd64" - else - platform="freebsd" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="kfreebsd" then - function resolvers.platform(t,k) - local platform,architecture="",os.getenv("HOSTTYPE") or os.resultof("uname -m") or "" - if find(architecture,"x86_64") then - platform="kfreebsd-amd64" - else - platform="kfreebsd-i386" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -else - function resolvers.platform(t,k) - local platform="linux" - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -end -function resolvers.bits(t,k) - local bits=find(os.platform,"64") and 64 or 32 - os.bits=bits - return bits -end -local t={ 8,9,"a","b" } -function os.uuid() - return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x", - random(0xFFFF),random(0xFFFF), - random(0x0FFF), - t[ceil(random(4))] or 8,random(0x0FFF), - random(0xFFFF), - random(0xFFFF),random(0xFFFF),random(0xFFFF) - ) -end -local d -function os.timezone(delta) - d=d or tonumber(tonumber(date("%H")-date("!%H"))) - if delta then - if d>0 then - return format("+%02i:00",d) - else - return format("-%02i:00",-d) - end - else - return 1 - end -end -local timeformat=format("%%s%s",os.timezone(true)) -local dateformat="!%Y-%m-%d %H:%M:%S" -local lasttime=nil -local lastdate=nil -function os.fulltime(t,default) - t=t and tonumber(t) or 0 - if t>0 then - elseif default then - return default - else - t=time() - end - if t~=lasttime then - lasttime=t - lastdate=format(timeformat,date(dateformat)) - end - return lastdate -end -local dateformat="%Y-%m-%d %H:%M:%S" -local lasttime=nil -local lastdate=nil -function os.localtime(t,default) - t=t and tonumber(t) or 0 - if t>0 then - elseif default then - return default - else - t=time() - end - if t~=lasttime then - lasttime=t - lastdate=date(dateformat,t) - end - return lastdate -end -function os.converttime(t,default) - local t=tonumber(t) - if t and t>0 then - return date(dateformat,t) - else - return default or "-" - end -end -local memory={} -local function which(filename) - local fullname=memory[filename] - if fullname==nil then - local suffix=file.suffix(filename) - local suffixes=suffix=="" and os.binsuffixes or { suffix } - for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do - local df=file.join(directory,filename) - for i=1,#suffixes do - local dfs=file.addsuffix(df,suffixes[i]) - if io.exists(dfs) then - fullname=dfs - break - end - end - end - if not fullname then - fullname=false - end - memory[filename]=fullname - end - return fullname -end -os.which=which -os.where=which -function os.today() - return date("!*t") -end -function os.now() - return date("!%Y-%m-%d %H:%M:%S") -end -if not os.sleep then - local socket=socket - function os.sleep(n) - if not socket then - socket=require("socket") - end - socket.sleep(n) - end -end -local function isleapyear(year) - return (year%400==0) or ((year%100~=0) and (year%4==0)) -end -os.isleapyear=isleapyear -local days={ 31,28,31,30,31,30,31,31,30,31,30,31 } -local function nofdays(year,month) - if not month then - return isleapyear(year) and 365 or 364 - else - return month==2 and isleapyear(year) and 29 or days[month] - end -end -os.nofdays=nofdays -function os.weekday(day,month,year) - return date("%w",time { year=year,month=month,day=day })+1 -end -function os.validdate(year,month,day) - if month<1 then - month=1 - elseif month>12 then - month=12 - end - if day<1 then - day=1 - else - local max=nofdays(year,month) - if day>max then - day=max - end - end - return year,month,day -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-file"] = package.loaded["l-file"] or true - --- original size: 18308, stripped down to: 9948 - -if not modules then modules={} end modules ['l-file']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -file=file or {} -local file=file -if not lfs then - lfs=optionalrequire("lfs") -end -if not lfs then - lfs={ - getcurrentdir=function() - return "." - end, - attributes=function() - return nil - end, - isfile=function(name) - local f=io.open(name,'rb') - if f then - f:close() - return true - end - end, - isdir=function(name) - print("you need to load lfs") - return false - end - } -elseif not lfs.isfile then - local attributes=lfs.attributes - function lfs.isdir(name) - return attributes(name,"mode")=="directory" - end - function lfs.isfile(name) - return attributes(name,"mode")=="file" - end -end -local insert,concat=table.insert,table.concat -local match,find,gmatch=string.match,string.find,string.gmatch -local lpegmatch=lpeg.match -local getcurrentdir,attributes=lfs.currentdir,lfs.attributes -local checkedsplit=string.checkedsplit -local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct -local colon=P(":") -local period=P(".") -local periods=P("..") -local fwslash=P("/") -local bwslash=P("\\") -local slashes=S("\\/") -local noperiod=1-period -local noslashes=1-slashes -local name=noperiod^1 -local suffix=period/""*(1-period-slashes)^1*-1 -local pattern=C((1-(slashes^1*noslashes^1*-1))^1)*P(1) -local function pathpart(name,default) - return name and lpegmatch(pattern,name) or default or "" -end -local pattern=(noslashes^0*slashes)^1*C(noslashes^1)*-1 -local function basename(name) - return name and lpegmatch(pattern,name) or name -end -local pattern=(noslashes^0*slashes^1)^0*Cs((1-suffix)^1)*suffix^0 -local function nameonly(name) - return name and lpegmatch(pattern,name) or name -end -local pattern=(noslashes^0*slashes)^0*(noperiod^1*period)^1*C(noperiod^1)*-1 -local function suffixonly(name) - return name and lpegmatch(pattern,name) or "" -end -local pattern=(noslashes^0*slashes)^0*noperiod^1*((period*C(noperiod^1))^1)*-1+Cc("") -local function suffixesonly(name) - if name then - return lpegmatch(pattern,name) - else - return "" - end -end -file.pathpart=pathpart -file.basename=basename -file.nameonly=nameonly -file.suffixonly=suffixonly -file.suffix=suffixonly -file.suffixesonly=suffixesonly -file.suffixes=suffixesonly -file.dirname=pathpart -file.extname=suffixonly -local drive=C(R("az","AZ"))*colon -local path=C((noslashes^0*slashes)^0) -local suffix=period*C(P(1-period)^0*P(-1)) -local base=C((1-suffix)^0) -local rest=C(P(1)^0) -drive=drive+Cc("") -path=path+Cc("") -base=base+Cc("") -suffix=suffix+Cc("") -local pattern_a=drive*path*base*suffix -local pattern_b=path*base*suffix -local pattern_c=C(drive*path)*C(base*suffix) -local pattern_d=path*rest -function file.splitname(str,splitdrive) - if not str then - elseif splitdrive then - return lpegmatch(pattern_a,str) - else - return lpegmatch(pattern_b,str) - end -end -function file.splitbase(str) - if str then - return lpegmatch(pattern_d,str) - else - return "",str - end -end -function file.nametotable(str,splitdrive) - if str then - local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str) - if splitdrive then - return { - path=path, - drive=drive, - subpath=subpath, - name=name, - base=base, - suffix=suffix, - } - else - return { - path=path, - name=name, - base=base, - suffix=suffix, - } - end - end -end -local pattern=Cs(((period*(1-period-slashes)^1*-1)/""+1)^1) -function file.removesuffix(name) - return name and lpegmatch(pattern,name) -end -local suffix=period/""*(1-period-slashes)^1*-1 -local pattern=Cs((noslashes^0*slashes^1)^0*((1-suffix)^1))*Cs(suffix) -function file.addsuffix(filename,suffix,criterium) - if not filename or not suffix or suffix=="" then - return filename - elseif criterium==true then - return filename.."."..suffix - elseif not criterium then - local n,s=lpegmatch(pattern,filename) - if not s or s=="" then - return filename.."."..suffix - else - return filename - end - else - local n,s=lpegmatch(pattern,filename) - if s and s~="" then - local t=type(criterium) - if t=="table" then - for i=1,#criterium do - if s==criterium[i] then - return filename - end - end - elseif t=="string" then - if s==criterium then - return filename - end - end - end - return (n or filename).."."..suffix - end -end -local suffix=period*(1-period-slashes)^1*-1 -local pattern=Cs((1-suffix)^0) -function file.replacesuffix(name,suffix) - if name and suffix and suffix~="" then - return lpegmatch(pattern,name).."."..suffix - else - return name - end -end -local reslasher=lpeg.replacer(P("\\"),"/") -function file.reslash(str) - return str and lpegmatch(reslasher,str) -end -function file.is_writable(name) - if not name then - elseif lfs.isdir(name) then - name=name.."/m_t_x_t_e_s_t.tmp" - local f=io.open(name,"wb") - if f then - f:close() - os.remove(name) - return true - end - elseif lfs.isfile(name) then - local f=io.open(name,"ab") - if f then - f:close() - return true - end - else - local f=io.open(name,"ab") - if f then - f:close() - os.remove(name) - return true - end - end - return false -end -local readable=P("r")*Cc(true) -function file.is_readable(name) - if name then - local a=attributes(name) - return a and lpegmatch(readable,a.permissions) or false - else - return false - end -end -file.isreadable=file.is_readable -file.iswritable=file.is_writable -function file.size(name) - if name then - local a=attributes(name) - return a and a.size or 0 - else - return 0 - end -end -function file.splitpath(str,separator) - return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator) -end -function file.joinpath(tab,separator) - return tab and concat(tab,separator or io.pathseparator) -end -local someslash=S("\\/") -local stripper=Cs(P(fwslash)^0/""*reslasher) -local isnetwork=someslash*someslash*(1-someslash)+(1-fwslash-colon)^1*colon -local isroot=fwslash^1*-1 -local hasroot=fwslash^1 -local reslasher=lpeg.replacer(S("\\/"),"/") -local deslasher=lpeg.replacer(S("\\/")^1,"/") -function file.join(...) - local lst={... } - local one=lst[1] - if lpegmatch(isnetwork,one) then - local one=lpegmatch(reslasher,one) - local two=lpegmatch(deslasher,concat(lst,"/",2)) - if lpegmatch(hasroot,two) then - return one..two - else - return one.."/"..two - end - elseif lpegmatch(isroot,one) then - local two=lpegmatch(deslasher,concat(lst,"/",2)) - if lpegmatch(hasroot,two) then - return two - else - return "/"..two - end - elseif one=="" then - return lpegmatch(stripper,concat(lst,"/",2)) - else - return lpegmatch(deslasher,concat(lst,"/")) - end -end -local drivespec=R("az","AZ")^1*colon -local anchors=fwslash+drivespec -local untouched=periods+(1-period)^1*P(-1) -local mswindrive=Cs(drivespec*(bwslash/"/"+fwslash)^0) -local mswinuncpath=(bwslash+fwslash)*(bwslash+fwslash)*Cc("//") -local splitstarter=(mswindrive+mswinuncpath+Cc(false))*Ct(lpeg.splitat(S("/\\")^1)) -local absolute=fwslash -function file.collapsepath(str,anchor) - if not str then - return - end - if anchor==true and not lpegmatch(anchors,str) then - str=getcurrentdir().."/"..str - end - if str=="" or str=="." then - return "." - elseif lpegmatch(untouched,str) then - return lpegmatch(reslasher,str) - end - local starter,oldelements=lpegmatch(splitstarter,str) - local newelements={} - local i=#oldelements - while i>0 do - local element=oldelements[i] - if element=='.' then - elseif element=='..' then - local n=i-1 - while n>0 do - local element=oldelements[n] - if element~='..' and element~='.' then - oldelements[n]='.' - break - else - n=n-1 - end - end - if n<1 then - insert(newelements,1,'..') - end - elseif element~="" then - insert(newelements,1,element) - end - i=i-1 - end - if #newelements==0 then - return starter or "." - elseif starter then - return starter..concat(newelements,'/') - elseif lpegmatch(absolute,str) then - return "/"..concat(newelements,'/') - else - newelements=concat(newelements,'/') - if anchor=="." and find(str,"^%./") then - return "./"..newelements - else - return newelements - end - end -end -local validchars=R("az","09","AZ","--","..") -local pattern_a=lpeg.replacer(1-validchars) -local pattern_a=Cs((validchars+P(1)/"-")^1) -local whatever=P("-")^0/"" -local pattern_b=Cs(whatever*(1-whatever*-1)^1) -function file.robustname(str,strict) - if str then - str=lpegmatch(pattern_a,str) or str - if strict then - return lpegmatch(pattern_b,str) or str - else - return str - end - end -end -file.readdata=io.loaddata -file.savedata=io.savedata -function file.copy(oldname,newname) - if oldname and newname then - local data=io.loaddata(oldname) - if data and data~="" then - file.savedata(newname,data) - end - end -end -local letter=R("az","AZ")+S("_-+") -local separator=P("://") -local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash -local rootbased=fwslash+letter*colon -lpeg.patterns.qualified=qualified -lpeg.patterns.rootbased=rootbased -function file.is_qualified_path(filename) - return filename and lpegmatch(qualified,filename)~=nil -end -function file.is_rootbased_path(filename) - return filename and lpegmatch(rootbased,filename)~=nil -end -function file.strip(name,dir) - if name then - local b,a=match(name,"^(.-)"..dir.."(.*)$") - return a~="" and a or name - end -end -function lfs.mkdirs(path) - local full="" - for sub in gmatch(path,"(/*[^\\/]+)") do - full=full..sub - lfs.mkdir(full) - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-gzip"] = package.loaded["l-gzip"] or true - --- original size: 1211, stripped down to: 1002 - -if not modules then modules={} end modules ['l-gzip']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if not gzip then - return -end -local suffix,suffixes=file.suffix,file.suffixes -function gzip.load(filename) - local f=io.open(filename,"rb") - if not f then - elseif suffix(filename)=="gz" then - f:close() - local g=gzip.open(filename,"rb") - if g then - local str=g:read("*all") - g:close() - return str - end - else - local str=f:read("*all") - f:close() - return str - end -end -function gzip.save(filename,data) - if suffix(filename)~="gz" then - filename=filename..".gz" - end - local f=io.open(filename,"wb") - if f then - local s=zlib.compress(data or "",9,nil,15+16) - f:write(s) - f:close() - return #s - end -end -function gzip.suffix(filename) - local suffix,extra=suffixes(filename) - local gzipped=extra=="gz" - return suffix,gzipped -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-md5"] = package.loaded["l-md5"] or true - --- original size: 3760, stripped down to: 2088 - -if not modules then modules={} end modules ['l-md5']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if not md5 then - md5=optionalrequire("md5") -end -if not md5 then - md5={ - sum=function(str) print("error: md5 is not loaded (sum ignored)") return str end, - sumhexa=function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end, - } -end -local md5,file=md5,file -local gsub,format,byte=string.gsub,string.format,string.byte -local md5sum=md5.sum -local function convert(str,fmt) - return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end)) -end -if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end -if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end -if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end -function file.needsupdating(oldname,newname,threshold) - local oldtime=lfs.attributes(oldname,"modification") - if oldtime then - local newtime=lfs.attributes(newname,"modification") - if not newtime then - return true - elseif newtime>=oldtime then - return false - elseif oldtime-newtime<(threshold or 1) then - return false - else - return true - end - else - return false - end -end -file.needs_updating=file.needsupdating -function file.syncmtimes(oldname,newname) - local oldtime=lfs.attributes(oldname,"modification") - if oldtime and lfs.isfile(newname) then - lfs.touch(newname,oldtime,oldtime) - end -end -function file.checksum(name) - if md5 then - local data=io.loaddata(name) - if data then - return md5.HEX(data) - end - end - return nil -end -function file.loadchecksum(name) - if md5 then - local data=io.loaddata(name..".md5") - return data and (gsub(data,"%s","")) - end - return nil -end -function file.savechecksum(name,checksum) - if not checksum then checksum=file.checksum(name) end - if checksum then - io.savedata(name..".md5",checksum) - return checksum - end - return nil -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-url"] = package.loaded["l-url"] or true - --- original size: 12292, stripped down to: 5585 - -if not modules then modules={} end modules ['l-url']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local char,format,byte=string.char,string.format,string.byte -local concat=table.concat -local tonumber,type=tonumber,type -local P,C,R,S,Cs,Cc,Ct,Cf,Cg,V=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Cf,lpeg.Cg,lpeg.V -local lpegmatch,lpegpatterns,replacer=lpeg.match,lpeg.patterns,lpeg.replacer -url=url or {} -local url=url -local tochar=function(s) return char(tonumber(s,16)) end -local colon=P(":") -local qmark=P("?") -local hash=P("#") -local slash=P("/") -local percent=P("%") -local endofstring=P(-1) -local hexdigit=R("09","AF","af") -local plus=P("+") -local nothing=Cc("") -local escapedchar=(percent*C(hexdigit*hexdigit))/tochar -local escaped=(plus/" ")+escapedchar -local noslash=P("/")/"" -local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2) -local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0) -local pathstr=Cs((escaped+(1- qmark-hash))^0) -local querystr=Cs(((1- hash))^0) -local fragmentstr=Cs((escaped+(1- endofstring))^0) -local scheme=schemestr*colon+nothing -local authority=slash*slash*authoritystr+nothing -local path=slash*pathstr+nothing -local query=qmark*querystr+nothing -local fragment=hash*fragmentstr+nothing -local validurl=scheme*authority*path*query*fragment -local parser=Ct(validurl) -lpegpatterns.url=validurl -lpegpatterns.urlsplitter=parser -local escapes={} -setmetatable(escapes,{ __index=function(t,k) - local v=format("%%%02X",byte(k)) - t[k]=v - return v -end }) -local escaper=Cs((R("09","AZ","az")^1+P(" ")/"%%20"+S("-./_")^1+P(1)/escapes)^0) -local unescaper=Cs((escapedchar+1)^0) -local getcleaner=Cs((P("+++")/"%%2B"+P("+")/"%%20"+P(1))^1) -lpegpatterns.urlunescaped=escapedchar -lpegpatterns.urlescaper=escaper -lpegpatterns.urlunescaper=unescaper -lpegpatterns.urlgetcleaner=getcleaner -function url.unescapeget(str) - return lpegmatch(getcleaner,str) -end -local function split(str) - return (type(str)=="string" and lpegmatch(parser,str)) or str -end -local isscheme=schemestr*colon*slash*slash -local function hasscheme(str) - if str then - local scheme=lpegmatch(isscheme,str) - return scheme~="" and scheme or false - else - return false - end -end -local rootletter=R("az","AZ")+S("_-+") -local separator=P("://") -local qualified=P(".")^0*P("/")+rootletter*P(":")+rootletter^1*separator+rootletter^1*P("/") -local rootbased=P("/")+rootletter*P(":") -local barswapper=replacer("|",":") -local backslashswapper=replacer("\\","/") -local equal=P("=") -local amp=P("&") -local key=Cs(((escapedchar+1)-equal )^0) -local value=Cs(((escapedchar+1)-amp -endofstring)^0) -local splitquery=Cf (Ct("")*P { "sequence", - sequence=V("pair")*(amp*V("pair"))^0, - pair=Cg(key*equal*value), -},rawset) -local function hashed(str) - if str=="" then - return { - scheme="invalid", - original=str, - } - end - local s=split(str) - local rawscheme=s[1] - local rawquery=s[4] - local somescheme=rawscheme~="" - local somequery=rawquery~="" - if not somescheme and not somequery then - s={ - scheme="file", - authority="", - path=str, - query="", - fragment="", - original=str, - noscheme=true, - filename=str, - } - else - local authority,path,filename=s[2],s[3] - if authority=="" then - filename=path - elseif path=="" then - filename="" - else - filename=authority.."/"..path - end - s={ - scheme=rawscheme, - authority=authority, - path=path, - query=lpegmatch(unescaper,rawquery), - queries=lpegmatch(splitquery,rawquery), - fragment=s[5], - original=str, - noscheme=false, - filename=filename, - } - end - return s -end -url.split=split -url.hasscheme=hasscheme -url.hashed=hashed -function url.addscheme(str,scheme) - if hasscheme(str) then - return str - elseif not scheme then - return "file:///"..str - else - return scheme..":///"..str - end -end -function url.construct(hash) - local fullurl,f={},0 - local scheme,authority,path,query,fragment=hash.scheme,hash.authority,hash.path,hash.query,hash.fragment - if scheme and scheme~="" then - f=f+1;fullurl[f]=scheme.."://" - end - if authority and authority~="" then - f=f+1;fullurl[f]=authority - end - if path and path~="" then - f=f+1;fullurl[f]="/"..path - end - if query and query~="" then - f=f+1;fullurl[f]="?"..query - end - if fragment and fragment~="" then - f=f+1;fullurl[f]="#"..fragment - end - return lpegmatch(escaper,concat(fullurl)) -end -local pattern=Cs(noslash*R("az","AZ")*(S(":|")/":")*noslash*P(1)^0) -function url.filename(filename) - local spec=hashed(filename) - local path=spec.path - return (spec.scheme=="file" and path and lpegmatch(pattern,path)) or filename -end -local function escapestring(str) - return lpegmatch(escaper,str) -end -url.escape=escapestring -function url.query(str) - if type(str)=="string" then - return lpegmatch(splitquery,str) or "" - else - return str - end -end -function url.toquery(data) - local td=type(data) - if td=="string" then - return #str and escape(data) or nil - elseif td=="table" then - if next(data) then - local t={} - for k,v in next,data do - t[#t+1]=format("%s=%s",k,escapestring(v)) - end - return concat(t,"&") - end - else - end -end -local pattern=Cs(noslash^0*(1-noslash*P(-1))^0) -function url.barepath(path) - if not path or path=="" then - return "" - else - return lpegmatch(pattern,path) - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-dir"] = package.loaded["l-dir"] or true - --- original size: 14768, stripped down to: 9107 - -if not modules then modules={} end modules ['l-dir']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,select=type,select -local find,gmatch,match,gsub=string.find,string.gmatch,string.match,string.gsub -local concat,insert,remove,unpack=table.concat,table.insert,table.remove,table.unpack -local lpegmatch=lpeg.match -local P,S,R,C,Cc,Cs,Ct,Cv,V=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cv,lpeg.V -dir=dir or {} -local dir=dir -local lfs=lfs -local attributes=lfs.attributes -local walkdir=lfs.dir -local isdir=lfs.isdir -local isfile=lfs.isfile -local currentdir=lfs.currentdir -local chdir=lfs.chdir -local mkdir=lfs.mkdir -local onwindows=os.type=="windows" or find(os.getenv("PATH"),";") -if not isdir then - function isdir(name) - local a=attributes(name) - return a and a.mode=="directory" - end - lfs.isdir=isdir -end -if not isfile then - function isfile(name) - local a=attributes(name) - return a and a.mode=="file" - end - lfs.isfile=isfile -end -function dir.current() - return (gsub(currentdir(),"\\","/")) -end -local lfsisdir=isdir -local function isdir(path) - path=gsub(path,"[/\\]+$","") - return lfsisdir(path) -end -lfs.isdir=isdir -local function globpattern(path,patt,recurse,action) - if path=="/" then - path=path.."." - elseif not find(path,"/$") then - path=path..'/' - end - if isdir(path) then - for name in walkdir(path) do - local full=path..name - local mode=attributes(full,'mode') - if mode=='file' then - if find(full,patt) then - action(full) - end - elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then - globpattern(full,patt,recurse,action) - end - end - end -end -dir.globpattern=globpattern -local function collectpattern(path,patt,recurse,result) - local ok,scanner - result=result or {} - if path=="/" then - ok,scanner,first=xpcall(function() return walkdir(path..".") end,function() end) - else - ok,scanner,first=xpcall(function() return walkdir(path) end,function() end) - end - if ok and type(scanner)=="function" then - if not find(path,"/$") then path=path..'/' end - for name in scanner,first do - local full=path..name - local attr=attributes(full) - local mode=attr.mode - if mode=='file' then - if find(full,patt) then - result[name]=attr - end - elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then - attr.list=collectpattern(full,patt,recurse) - result[name]=attr - end - end - end - return result -end -dir.collectpattern=collectpattern -local separator -if onwindows then - local slash=S("/\\")/"/" - pattern=Ct { - [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), - [2]=Cs(((1-S("*?/\\"))^0*slash)^0), - [3]=Cs(P(1)^0) - } -else - pattern=Ct { - [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), - [2]=C(((1-S("*?/"))^0*P("/"))^0), - [3]=C(P(1)^0) - } -end -local filter=Cs (( - P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1) -)^0 ) -local function glob(str,t) - if type(t)=="function" then - if type(str)=="table" then - for s=1,#str do - glob(str[s],t) - end - elseif isfile(str) then - t(str) - else - local split=lpegmatch(pattern,str) - if split then - local root,path,base=split[1],split[2],split[3] - local recurse=find(base,"%*%*") - local start=root..path - local result=lpegmatch(filter,start..base) - globpattern(start,result,recurse,t) - end - end - else - if type(str)=="table" then - local t=t or {} - for s=1,#str do - glob(str[s],t) - end - return t - elseif isfile(str) then - if t then - t[#t+1]=str - return t - else - return { str } - end - else - local split=lpegmatch(pattern,str) - if split then - local t=t or {} - local action=action or function(name) t[#t+1]=name end - local root,path,base=split[1],split[2],split[3] - local recurse=find(base,"%*%*") - local start=root..path - local result=lpegmatch(filter,start..base) - globpattern(start,result,recurse,action) - return t - else - return {} - end - end - end -end -dir.glob=glob -local function globfiles(path,recurse,func,files) - if type(func)=="string" then - local s=func - func=function(name) return find(name,s) end - end - files=files or {} - local noffiles=#files - for name in walkdir(path) do - if find(name,"^%.") then - else - local mode=attributes(name,'mode') - if mode=="directory" then - if recurse then - globfiles(path.."/"..name,recurse,func,files) - end - elseif mode=="file" then - if not func or func(name) then - noffiles=noffiles+1 - files[noffiles]=path.."/"..name - end - end - end - end - return files -end -dir.globfiles=globfiles -function dir.ls(pattern) - return concat(glob(pattern),"\n") -end -local make_indeed=true -if onwindows then - function dir.mkdirs(...) - local n=select("#",...) - local str - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - local s=select(i,...) - if s=="" then - elseif str=="" then - str=s - else - str=str.."/"..s - end - end - end - local pth="" - local drive=false - local first,middle,last=match(str,"^(//)(//*)(.*)$") - if first then - else - first,last=match(str,"^(//)/*(.-)$") - if first then - middle,last=match(str,"([^/]+)/+(.-)$") - if middle then - pth="//"..middle - else - pth="//"..last - last="" - end - else - first,middle,last=match(str,"^([a-zA-Z]:)(/*)(.-)$") - if first then - pth,drive=first..middle,true - else - middle,last=match(str,"^(/*)(.-)$") - if not middle then - last=str - end - end - end - end - for s in gmatch(last,"[^/]+") do - if pth=="" then - pth=s - elseif drive then - pth,drive=pth..s,false - else - pth=pth.."/"..s - end - if make_indeed and not isdir(pth) then - mkdir(pth) - end - end - return pth,(isdir(pth)==true) - end -else - function dir.mkdirs(...) - local n=select("#",...) - local str,pth - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - if s and s~="" then - if str~="" then - str=str.."/"..s - else - str=s - end - end - end - end - str=gsub(str,"/+","/") - if find(str,"^/") then - pth="/" - for s in gmatch(str,"[^/]+") do - local first=(pth=="/") - if first then - pth=pth..s - else - pth=pth.."/"..s - end - if make_indeed and not first and not isdir(pth) then - mkdir(pth) - end - end - else - pth="." - for s in gmatch(str,"[^/]+") do - pth=pth.."/"..s - if make_indeed and not isdir(pth) then - mkdir(pth) - end - end - end - return pth,(isdir(pth)==true) - end -end -dir.makedirs=dir.mkdirs -if onwindows then - function dir.expandname(str) - local first,nothing,last=match(str,"^(//)(//*)(.*)$") - if first then - first=dir.current().."/" - end - if not first then - first,last=match(str,"^(//)/*(.*)$") - end - if not first then - first,last=match(str,"^([a-zA-Z]:)(.*)$") - if first and not find(last,"^/") then - local d=currentdir() - if chdir(first) then - first=dir.current() - end - chdir(d) - end - end - if not first then - first,last=dir.current(),str - end - last=gsub(last,"//","/") - last=gsub(last,"/%./","/") - last=gsub(last,"^/*","") - first=gsub(first,"/*$","") - if last=="" or last=="." then - return first - else - return first.."/"..last - end - end -else - function dir.expandname(str) - if not find(str,"^/") then - str=currentdir().."/"..str - end - str=gsub(str,"//","/") - str=gsub(str,"/%./","/") - str=gsub(str,"(.)/%.$","%1") - return str - end -end -file.expandname=dir.expandname -local stack={} -function dir.push(newdir) - insert(stack,currentdir()) - if newdir and newdir~="" then - chdir(newdir) - end -end -function dir.pop() - local d=remove(stack) - if d then - chdir(d) - end - return d -end -local function found(...) - for i=1,select("#",...) do - local path=select(i,...) - local kind=type(path) - if kind=="string" then - if isdir(path) then - return path - end - elseif kind=="table" then - local path=found(unpack(path)) - if path then - return path - end - end - end -end -dir.found=found - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-boolean"] = package.loaded["l-boolean"] or true - --- original size: 1809, stripped down to: 1527 - -if not modules then modules={} end modules ['l-boolean']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,tonumber=type,tonumber -boolean=boolean or {} -local boolean=boolean -function boolean.tonumber(b) - if b then return 1 else return 0 end -end -function toboolean(str,tolerant) - if str==nil then - return false - elseif str==false then - return false - elseif str==true then - return true - elseif str=="true" then - return true - elseif str=="false" then - return false - elseif not tolerant then - return false - elseif str==0 then - return false - elseif (tonumber(str) or 0)>0 then - return true - else - return str=="yes" or str=="on" or str=="t" - end -end -string.toboolean=toboolean -function string.booleanstring(str) - if str=="0" then - return false - elseif str=="1" then - return true - elseif str=="" then - return false - elseif str=="false" then - return false - elseif str=="true" then - return true - elseif (tonumber(str) or 0)>0 then - return true - else - return str=="yes" or str=="on" or str=="t" - end -end -function string.is_boolean(str,default) - if type(str)=="string" then - if str=="true" or str=="yes" or str=="on" or str=="t" or str=="1" then - return true - elseif str=="false" or str=="no" or str=="off" or str=="f" or str=="0" then - return false - end - end - return default -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-unicode"] = package.loaded["l-unicode"] or true - --- original size: 33473, stripped down to: 14938 - -if not modules then modules={} end modules ['l-unicode']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utf=utf or (unicode and unicode.utf8) or {} -utf.characters=utf.characters or string.utfcharacters -utf.values=utf.values or string.utfvalues -local type=type -local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch -local concat=table.concat -local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local bytepairs=string.bytepairs -local finder=lpeg.finder -local replacer=lpeg.replacer -local utfvalues=utf.values -local utfgmatch=utf.gmatch -local p_utftype=patterns.utftype -local p_utfstricttype=patterns.utfstricttype -local p_utfoffset=patterns.utfoffset -local p_utf8char=patterns.utf8char -local p_utf8byte=patterns.utf8byte -local p_utfbom=patterns.utfbom -local p_newline=patterns.newline -local p_whitespace=patterns.whitespace -if not unicode then - unicode={ utf=utf } -end -if not utf.char then - local floor,char=math.floor,string.char - function utf.char(n) - if n<0x80 then - return char(n) - elseif n<0x800 then - return char( - 0xC0+floor(n/0x40), - 0x80+(n%0x40) - ) - elseif n<0x10000 then - return char( - 0xE0+floor(n/0x1000), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - elseif n<0x200000 then - return char( - 0xF0+floor(n/0x40000), - 0x80+(floor(n/0x1000)%0x40), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - else - return "" - end - end -end -if not utf.byte then - local utf8byte=patterns.utf8byte - function utf.byte(c) - return lpegmatch(utf8byte,c) - end -end -local utfchar,utfbyte=utf.char,utf.byte -function utf.filetype(data) - return data and lpegmatch(p_utftype,data) or "unknown" -end -local toentities=Cs ( - ( - patterns.utf8one+( - patterns.utf8two+patterns.utf8three+patterns.utf8four - )/function(s) local b=utfbyte(s) if b<127 then return s else return format("&#%X;",b) end end - )^0 -) -patterns.toentities=toentities -function utf.toentities(str) - return lpegmatch(toentities,str) -end -local one=P(1) -local two=C(1)*C(1) -local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1) -local pattern=P("\254\255")*Cs(( - four/function(a,b,c,d) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(a,b) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 )+P("\255\254")*Cs(( - four/function(b,a,d,c) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(b,a) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 ) -function string.toutf(s) - return lpegmatch(pattern,s) or s -end -local validatedutf=Cs ( - ( - patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�" - )^0 -) -patterns.validatedutf=validatedutf -function utf.is_valid(str) - return type(str)=="string" and lpegmatch(validatedutf,str) or false -end -if not utf.len then - local n,f=0,1 - local utfcharcounter=patterns.utfbom^-1*Cmt ( - Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1, - function(_,t,d) - n=n+(t-f)/d - f=t - return true - end - )^0 - function utf.len(str) - n,f=0,1 - lpegmatch(utfcharcounter,str or "") - return n - end -end -utf.length=utf.len -if not utf.sub then - local utflength=utf.length - local b,e,n,first,last=0,0,0,0,0 - local function slide_zero(s,p) - n=n+1 - if n>=last then - e=p-1 - else - return p - end - end - local function slide_one(s,p) - n=n+1 - if n==first then - b=p - end - if n>=last then - e=p-1 - else - return p - end - end - local function slide_two(s,p) - n=n+1 - if n==first then - b=p - else - return true - end - end - local pattern_zero=Cmt(p_utf8char,slide_zero)^0 - local pattern_one=Cmt(p_utf8char,slide_one )^0 - local pattern_two=Cmt(p_utf8char,slide_two )^0 - function utf.sub(str,start,stop) - if not start then - return str - end - if start==0 then - start=1 - end - if not stop then - if start<0 then - local l=utflength(str) - start=l+start - else - start=start-1 - end - b,n,first=0,0,start - lpegmatch(pattern_two,str) - if n>=first then - return sub(str,b) - else - return "" - end - end - if start<0 or stop<0 then - local l=utf.length(str) - if start<0 then - start=l+start - if start<=0 then - start=1 - else - start=start+1 - end - end - if stop<0 then - stop=l+stop - if stop==0 then - stop=1 - else - stop=stop+1 - end - end - end - if start>stop then - return "" - elseif start>1 then - b,e,n,first,last=0,0,0,start-1,stop - lpegmatch(pattern_one,str) - if n>=first and e==0 then - e=#str - end - return sub(str,b,e) - else - b,e,n,last=1,0,0,stop - lpegmatch(pattern_zero,str) - if e==0 then - e=#str - end - return sub(str,b,e) - end - end -end -function utf.remapper(mapping) - local pattern=Cs((p_utf8char/mapping)^0) - return function(str) - if not str or str=="" then - return "" - else - return lpegmatch(pattern,str) - end - end,pattern -end -function utf.replacer(t) - local r=replacer(t,false,false,true) - return function(str) - return lpegmatch(r,str) - end -end -function utf.subtituter(t) - local f=finder (t) - local r=replacer(t,false,false,true) - return function(str) - local i=lpegmatch(f,str) - if not i then - return str - elseif i>#str then - return str - else - return lpegmatch(r,str) - end - end -end -local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline) -local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8char)^0) -local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8char))^0) -local utfcharsplitter_raw=Ct(C(p_utf8char)^0) -patterns.utflinesplitter=utflinesplitter -function utf.splitlines(str) - return lpegmatch(utflinesplitter,str or "") -end -function utf.split(str,ignorewhitespace) - if ignorewhitespace then - return lpegmatch(utfcharsplitter_iws,str or "") - else - return lpegmatch(utfcharsplitter_ows,str or "") - end -end -function utf.totable(str) - return lpegmatch(utfcharsplitter_raw,str) -end -function utf.magic(f) - local str=f:read(4) or "" - local off=lpegmatch(p_utfoffset,str) - if off<4 then - f:seek('set',off) - end - return lpegmatch(p_utftype,str) -end -local utf16_to_utf8_be,utf16_to_utf8_le -local utf32_to_utf8_be,utf32_to_utf8_le -local utf_16_be_linesplitter=patterns.utfbom_16_be^-1*lpeg.tsplitat(patterns.utf_16_be_nl) -local utf_16_le_linesplitter=patterns.utfbom_16_le^-1*lpeg.tsplitat(patterns.utf_16_le_nl) -if bytepairs then - utf16_to_utf8_be=function(t) - if type(t)=="string" then - t=lpegmatch(utf_16_be_linesplitter,t) - end - local result={} - for i=1,#t do - local r,more=0,0 - for left,right in bytepairs(t[i]) do - if right then - local now=256*left+right - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - r=r+1 - result[r]=utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - else - r=r+1 - result[r]=utfchar(now) - end - end - end - t[i]=concat(result,"",1,r) - end - return t - end - utf16_to_utf8_le=function(t) - if type(t)=="string" then - t=lpegmatch(utf_16_le_linesplitter,t) - end - local result={} - for i=1,#t do - local r,more=0,0 - for left,right in bytepairs(t[i]) do - if right then - local now=256*right+left - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - r=r+1 - result[r]=utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - else - r=r+1 - result[r]=utfchar(now) - end - end - end - t[i]=concat(result,"",1,r) - end - return t - end - utf32_to_utf8_be=function(t) - if type(t)=="string" then - t=lpegmatch(utflinesplitter,t) - end - local result={} - for i=1,#t do - local r,more=0,-1 - for a,b in bytepairs(t[i]) do - if a and b then - if more<0 then - more=256*256*256*a+256*256*b - else - r=r+1 - result[t]=utfchar(more+256*a+b) - more=-1 - end - else - break - end - end - t[i]=concat(result,"",1,r) - end - return t - end - utf32_to_utf8_le=function(t) - if type(t)=="string" then - t=lpegmatch(utflinesplitter,t) - end - local result={} - for i=1,#t do - local r,more=0,-1 - for a,b in bytepairs(t[i]) do - if a and b then - if more<0 then - more=256*b+a - else - r=r+1 - result[t]=utfchar(more+256*256*256*b+256*256*a) - more=-1 - end - else - break - end - end - t[i]=concat(result,"",1,r) - end - return t - end -else - utf16_to_utf8_be=function(t) - if type(t)=="string" then - t=lpegmatch(utf_16_be_linesplitter,t) - end - local result={} - for i=1,#t do - local r,more=0,0 - for left,right in gmatch(t[i],"(.)(.)") do - if left=="\000" then - r=r+1 - result[r]=utfchar(byte(right)) - elseif right then - local now=256*byte(left)+byte(right) - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - r=r+1 - result[r]=utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - else - r=r+1 - result[r]=utfchar(now) - end - end - end - t[i]=concat(result,"",1,r) - end - return t - end - utf16_to_utf8_le=function(t) - if type(t)=="string" then - t=lpegmatch(utf_16_le_linesplitter,t) - end - local result={} - for i=1,#t do - local r,more=0,0 - for left,right in gmatch(t[i],"(.)(.)") do - if right=="\000" then - r=r+1 - result[r]=utfchar(byte(left)) - elseif right then - local now=256*byte(right)+byte(left) - if more>0 then - now=(more-0xD800)*0x400+(now-0xDC00)+0x10000 - more=0 - r=r+1 - result[r]=utfchar(now) - elseif now>=0xD800 and now<=0xDBFF then - more=now - else - r=r+1 - result[r]=utfchar(now) - end - end - end - t[i]=concat(result,"",1,r) - end - return t - end - utf32_to_utf8_le=function() return {} end - utf32_to_utf8_be=function() return {} end -end -utf.utf16_to_utf8_le=utf16_to_utf8_le -utf.utf16_to_utf8_be=utf16_to_utf8_be -utf.utf32_to_utf8_le=utf32_to_utf8_le -utf.utf32_to_utf8_be=utf32_to_utf8_be -function utf.utf8_to_utf8(t) - return type(t)=="string" and lpegmatch(utflinesplitter,t) or t -end -function utf.utf16_to_utf8(t,endian) - return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t -end -function utf.utf32_to_utf8(t,endian) - return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t -end -local function little(c) - local b=byte(c) - if b<0x10000 then - return char(b%256,b/256) - else - b=b-0x10000 - local b1,b2=b/1024+0xD800,b%1024+0xDC00 - return char(b1%256,b1/256,b2%256,b2/256) - end -end -local function big(c) - local b=byte(c) - if b<0x10000 then - return char(b/256,b%256) - else - b=b-0x10000 - local b1,b2=b/1024+0xD800,b%1024+0xDC00 - return char(b1/256,b1%256,b2/256,b2%256) - end -end -local _,l_remap=utf.remapper(little) -local _,b_remap=utf.remapper(big) -function utf.utf8_to_utf16_be(str,nobom) - if nobom then - return lpegmatch(b_remap,str) - else - return char(254,255)..lpegmatch(b_remap,str) - end -end -function utf.utf8_to_utf16_le(str,nobom) - if nobom then - return lpegmatch(l_remap,str) - else - return char(255,254)..lpegmatch(l_remap,str) - end -end -function utf.utf8_to_utf16(str,littleendian,nobom) - if littleendian then - return utf.utf8_to_utf16_le(str,nobom) - else - return utf.utf8_to_utf16_be(str,nobom) - end -end -local pattern=Cs ( - (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0 -) -function utf.tocodes(str,separator) - return lpegmatch(pattern,str,1,separator or " ") -end -function utf.ustring(s) - return format("U+%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.xstring(s) - return format("0x%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.toeight(str) - if not str then - return nil - end - local utftype=lpegmatch(p_utfstricttype,str) - if utftype=="utf-8" then - return sub(str,4) - elseif utftype=="utf-16-le" then - return utf16_to_utf8_le(str) - elseif utftype=="utf-16-be" then - return utf16_to_utf8_ne(str) - else - return str - end -end -local p_nany=p_utf8char/"" -if utfgmatch then - function utf.count(str,what) - if type(what)=="string" then - local n=0 - for _ in utfgmatch(str,what) do - n=n+1 - end - return n - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -else - local cache={} - function utf.count(str,what) - if type(what)=="string" then - local p=cache[what] - if not p then - p=Cs((P(what)/" "+p_nany)^0) - cache[p]=p - end - return #lpegmatch(p,str) - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -end -if not utf.characters then - function utf.characters(str) - return gmatch(str,".[\128-\191]*") - end - string.utfcharacters=utf.characters -end -if not utf.values then - local find=string.find - local dummy=function() - end - function utf.values(str) - local n=#str - if n==0 then - return dummy - elseif n==1 then - return function() return utfbyte(str) end - else - local p=1 - return function() - local b,e=find(str,".[\128-\191]*",p) - if b then - p=e+1 - return utfbyte(sub(str,b,e)) - end - end - end - end - string.utfvalues=utf.values -end -function utf.chrlen(u) - return - (u<0x80 and 1) or - (u<0xE0 and 2) or - (u<0xF0 and 3) or - (u<0xF8 and 4) or - (u<0xFC and 5) or - (u<0xFE and 6) or 0 -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-math"] = package.loaded["l-math"] or true - --- original size: 915, stripped down to: 836 - -if not modules then modules={} end modules ['l-math']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan -if not math.round then - function math.round(x) return floor(x+0.5) end -end -if not math.div then - function math.div(n,m) return floor(n/m) end -end -if not math.mod then - function math.mod(n,m) return n%m end -end -local pipi=2*math.pi/360 -if not math.sind then - function math.sind(d) return sin(d*pipi) end - function math.cosd(d) return cos(d*pipi) end - function math.tand(d) return tan(d*pipi) end -end -if not math.odd then - function math.odd (n) return n%2~=0 end - function math.even(n) return n%2==0 end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-str"] = package.loaded["util-str"] or true - --- original size: 29502, stripped down to: 16632 - -if not modules then modules={} end modules ['util-str']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utilities=utilities or {} -utilities.strings=utilities.strings or {} -local strings=utilities.strings -local format,gsub,rep,sub=string.format,string.gsub,string.rep,string.sub -local load,dump=load,string.dump -local tonumber,type,tostring=tonumber,type,tostring -local unpack,concat=table.unpack,table.concat -local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc -local patterns,lpegmatch=lpeg.patterns,lpeg.match -local utfchar,utfbyte=utf.char,utf.byte -local loadstripped=nil -if _LUAVERSION<5.2 then - loadstripped=function(str,shortcuts) - return load(str) - end -else - loadstripped=function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end -end -if not number then number={} end -local stripper=patterns.stripzeros -local function points(n) - return (not n or n==0) and "0pt" or lpegmatch(stripper,format("%.5fpt",n/65536)) -end -local function basepoints(n) - return (not n or n==0) and "0bp" or lpegmatch(stripper,format("%.5fbp",n*(7200/7227)/65536)) -end -number.points=points -number.basepoints=basepoints -local rubish=patterns.spaceortab^0*patterns.newline -local anyrubish=patterns.spaceortab+patterns.newline -local anything=patterns.anything -local stripped=(patterns.spaceortab^1/"")*patterns.newline -local leading=rubish^0/"" -local trailing=(anyrubish^1*patterns.endofstring)/"" -local redundant=rubish^3/"\n" -local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end -local repeaters={} -function strings.newrepeater(str,offset) - offset=offset or 0 - local s=repeaters[str] - if not s then - s={} - repeaters[str]=s - end - local t=s[offset] - if t then - return t - end - t={} - setmetatable(t,{ __index=function(t,k) - if not k then - return "" - end - local n=k+offset - local s=n>0 and rep(str,n) or "" - t[k]=s - return s - end }) - s[offset]=t - return t -end -local extra,tab,start=0,0,4,0 -local nspaces=strings.newrepeater(" ") -string.nspaces=nspaces -local pattern=Carg(1)/function(t) - extra,tab,start=0,t or 7,1 - end*Cs(( - Cp()*patterns.tab/function(position) - local current=(position-start+1)+extra - local spaces=tab-(current-1)%tab - if spaces>0 then - extra=extra+spaces-1 - return nspaces[spaces] - else - return "" - end - end+patterns.newline*Cp()/function(position) - extra,start=0,position - end+patterns.anything - )^1) -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end -function strings.striplong(str) - str=gsub(str,"^%s*","") - str=gsub(str,"[\n\r]+ *","\n") - return str -end -function strings.nice(str) - str=gsub(str,"[:%-+_]+"," ") - return str -end -local n=0 -local sequenced=table.sequenced -function string.autodouble(s,sep) - if s==nil then - return '""' - end - local t=type(s) - if t=="number" then - return tostring(s) - end - if t=="table" then - return ('"'..sequenced(s,sep or ",")..'"') - end - return ('"'..tostring(s)..'"') -end -function string.autosingle(s,sep) - if s==nil then - return "''" - end - local t=type(s) - if t=="number" then - return tostring(s) - end - if t=="table" then - return ("'"..sequenced(s,sep or ",").."'") - end - return ("'"..tostring(s).."'") -end -local tracedchars={} -string.tracedchars=tracedchars -strings.tracers=tracedchars -function string.tracedchar(b) - if type(b)=="number" then - return tracedchars[b] or (utfchar(b).." (U+"..format('%05X',b)..")") - else - local c=utfbyte(b) - return tracedchars[c] or (b.." (U+"..format('%05X',c)..")") - end -end -function number.signed(i) - if i>0 then - return "+",i - else - return "-",-i - end -end -local zero=P("0")^1/"" -local plus=P("+")/"" -local minus=P("-") -local separator=S(".") -local digit=R("09") -local trailing=zero^1*#S("eE") -local exponent=(S("eE")*(plus+Cs((minus*zero^0*P(-1))/"")+minus)*zero^0*(P(-1)*Cc("0")+P(1)^1)) -local pattern_a=Cs(minus^0*digit^1*(separator/""*trailing+separator*(trailing+digit)^0)*exponent) -local pattern_b=Cs((exponent+P(1))^0) -function number.sparseexponent(f,n) - if not n then - n=f - f="%e" - end - local tn=type(n) - if tn=="string" then - local m=tonumber(n) - if m then - return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,m)) - end - elseif tn=="number" then - return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,n)) - end - return tostring(n) -end -local template=[[ -%s -%s -return function(%s) return %s end -]] -local preamble,environment="",{} -if _LUAVERSION<5.2 then - preamble=[[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] -else - environment={ - global=global or _G, - lpeg=lpeg, - type=type, - tostring=tostring, - tonumber=tonumber, - format=string.format, - concat=table.concat, - signed=number.signed, - points=number.points, - basepoints=number.basepoints, - utfchar=utf.char, - utfbyte=utf.byte, - lpegmatch=lpeg.match, - nspaces=string.nspaces, - tracedchar=string.tracedchar, - autosingle=string.autosingle, - autodouble=string.autodouble, - sequenced=table.sequenced, - formattednumber=number.formatted, - sparseexponent=number.sparseexponent, - } -end -local arguments={ "a1" } -setmetatable(arguments,{ __index=function(t,k) - local v=t[k-1]..",a"..k - t[k]=v - return v - end -}) -local prefix_any=C((S("+- .")+R("09"))^0) -local prefix_tab=P("{")*C((1-P("}"))^0)*P("}")+C((1-R("az","AZ","09","%%"))^0) -local format_s=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%ss',a%s)",f,n) - else - return format("(a%s or '')",n) - end -end -local format_S=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%ss',tostring(a%s))",f,n) - else - return format("tostring(a%s)",n) - end -end -local format_q=function() - n=n+1 - return format("(a%s and format('%%q',a%s) or '')",n,n) -end -local format_Q=function() - n=n+1 - return format("format('%%q',tostring(a%s))",n) -end -local format_i=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%si',a%s)",f,n) - else - return format("format('%%i',a%s)",n) - end -end -local format_d=format_i -local format_I=function(f) - n=n+1 - return format("format('%%s%%%si',signed(a%s))",f,n) -end -local format_f=function(f) - n=n+1 - return format("format('%%%sf',a%s)",f,n) -end -local format_g=function(f) - n=n+1 - return format("format('%%%sg',a%s)",f,n) -end -local format_G=function(f) - n=n+1 - return format("format('%%%sG',a%s)",f,n) -end -local format_e=function(f) - n=n+1 - return format("format('%%%se',a%s)",f,n) -end -local format_E=function(f) - n=n+1 - return format("format('%%%sE',a%s)",f,n) -end -local format_j=function(f) - n=n+1 - return format("sparseexponent('%%%se',a%s)",f,n) -end -local format_J=function(f) - n=n+1 - return format("sparseexponent('%%%sE',a%s)",f,n) -end -local format_x=function(f) - n=n+1 - return format("format('%%%sx',a%s)",f,n) -end -local format_X=function(f) - n=n+1 - return format("format('%%%sX',a%s)",f,n) -end -local format_o=function(f) - n=n+1 - return format("format('%%%so',a%s)",f,n) -end -local format_c=function() - n=n+1 - return format("utfchar(a%s)",n) -end -local format_C=function() - n=n+1 - return format("tracedchar(a%s)",n) -end -local format_r=function(f) - n=n+1 - return format("format('%%%s.0f',a%s)",f,n) -end -local format_h=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_H=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_u=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_U=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_p=function() - n=n+1 - return format("points(a%s)",n) -end -local format_b=function() - n=n+1 - return format("basepoints(a%s)",n) -end -local format_t=function(f) - n=n+1 - if f and f~="" then - return format("concat(a%s,%q)",n,f) - else - return format("concat(a%s)",n) - end -end -local format_T=function(f) - n=n+1 - if f and f~="" then - return format("sequenced(a%s,%q)",n,f) - else - return format("sequenced(a%s)",n) - end -end -local format_l=function() - n=n+1 - return format("(a%s and 'true' or 'false')",n) -end -local format_L=function() - n=n+1 - return format("(a%s and 'TRUE' or 'FALSE')",n) -end -local format_N=function() - n=n+1 - return format("tostring(tonumber(a%s) or a%s)",n,n) -end -local format_a=function(f) - n=n+1 - if f and f~="" then - return format("autosingle(a%s,%q)",n,f) - else - return format("autosingle(a%s)",n) - end -end -local format_A=function(f) - n=n+1 - if f and f~="" then - return format("autodouble(a%s,%q)",n,f) - else - return format("autodouble(a%s)",n) - end -end -local format_w=function(f) - n=n+1 - f=tonumber(f) - if f then - return format("nspaces[%s+a%s]",f,n) - else - return format("nspaces[a%s]",n) - end -end -local format_W=function(f) - return format("nspaces[%s]",tonumber(f) or 0) -end -local digit=patterns.digit -local period=patterns.period -local three=digit*digit*digit -local splitter=Cs ( - (((1-(three^1*period))^1+C(three))*(Carg(1)*three)^1+C((1-period)^1))*(P(1)/""*Carg(2))*C(2) -) -patterns.formattednumber=splitter -function number.formatted(n,sep1,sep2) - local s=type(s)=="string" and n or format("%0.2f",n) - if sep1==true then - return lpegmatch(splitter,s,1,".",",") - elseif sep1=="." then - return lpegmatch(splitter,s,1,sep1,sep2 or ",") - elseif sep1=="," then - return lpegmatch(splitter,s,1,sep1,sep2 or ".") - else - return lpegmatch(splitter,s,1,sep1 or ",",sep2 or ".") - end -end -local format_m=function(f) - n=n+1 - if not f or f=="" then - f="," - end - return format([[formattednumber(a%s,%q,".")]],n,f) -end -local format_M=function(f) - n=n+1 - if not f or f=="" then - f="." - end - return format([[formattednumber(a%s,%q,",")]],n,f) -end -local format_z=function(f) - n=n+(tonumber(f) or 1) - return "''" -end -local format_rest=function(s) - return format("%q",s) -end -local format_extension=function(extensions,f,name) - local extension=extensions[name] or "tostring(%s)" - local f=tonumber(f) or 1 - if f==0 then - return extension - elseif f==1 then - n=n+1 - local a="a"..n - return format(extension,a,a) - elseif f<0 then - local a="a"..(n+f+1) - return format(extension,a,a) - else - local t={} - for i=1,f do - n=n+1 - t[#t+1]="a"..n - end - return format(extension,unpack(t)) - end -end -local builder=Cs { "start", - start=( - ( - P("%")/""*( - V("!") -+V("s")+V("q")+V("i")+V("d")+V("f")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o") -+V("c")+V("C")+V("S") -+V("Q") -+V("N") -+V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("b")+V("t")+V("T")+V("l")+V("L")+V("I")+V("w") -+V("W") -+V("a") -+V("A") -+V("j")+V("J") -+V("m")+V("M") -+V("z") -+V("*") - )+V("*") - )*(P(-1)+Carg(1)) - )^0, - ["s"]=(prefix_any*P("s"))/format_s, - ["q"]=(prefix_any*P("q"))/format_q, - ["i"]=(prefix_any*P("i"))/format_i, - ["d"]=(prefix_any*P("d"))/format_d, - ["f"]=(prefix_any*P("f"))/format_f, - ["g"]=(prefix_any*P("g"))/format_g, - ["G"]=(prefix_any*P("G"))/format_G, - ["e"]=(prefix_any*P("e"))/format_e, - ["E"]=(prefix_any*P("E"))/format_E, - ["x"]=(prefix_any*P("x"))/format_x, - ["X"]=(prefix_any*P("X"))/format_X, - ["o"]=(prefix_any*P("o"))/format_o, - ["S"]=(prefix_any*P("S"))/format_S, - ["Q"]=(prefix_any*P("Q"))/format_S, - ["N"]=(prefix_any*P("N"))/format_N, - ["c"]=(prefix_any*P("c"))/format_c, - ["C"]=(prefix_any*P("C"))/format_C, - ["r"]=(prefix_any*P("r"))/format_r, - ["h"]=(prefix_any*P("h"))/format_h, - ["H"]=(prefix_any*P("H"))/format_H, - ["u"]=(prefix_any*P("u"))/format_u, - ["U"]=(prefix_any*P("U"))/format_U, - ["p"]=(prefix_any*P("p"))/format_p, - ["b"]=(prefix_any*P("b"))/format_b, - ["t"]=(prefix_tab*P("t"))/format_t, - ["T"]=(prefix_tab*P("T"))/format_T, - ["l"]=(prefix_any*P("l"))/format_l, - ["L"]=(prefix_any*P("L"))/format_L, - ["I"]=(prefix_any*P("I"))/format_I, - ["w"]=(prefix_any*P("w"))/format_w, - ["W"]=(prefix_any*P("W"))/format_W, - ["j"]=(prefix_any*P("j"))/format_j, - ["J"]=(prefix_any*P("J"))/format_J, - ["m"]=(prefix_tab*P("m"))/format_m, - ["M"]=(prefix_tab*P("M"))/format_M, - ["z"]=(prefix_any*P("z"))/format_z, - ["a"]=(prefix_any*P("a"))/format_a, - ["A"]=(prefix_any*P("A"))/format_A, - ["*"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_rest, - ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension, -} -local direct=Cs ( - P("%")*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*P(-1)/[[local format = string.format return function(str) return format("%0",str) end]] -) -local function make(t,str) - local f - local p - local p=lpegmatch(direct,str) - if p then - f=loadstripped(p)() - else - n=0 - p=lpegmatch(builder,str,1,"..",t._extensions_) - if n>0 then - p=format(template,preamble,t._preamble_,arguments[n],p) - f=loadstripped(p,t._environment_)() - else - f=function() return str end - end - end - t[str]=f - return f -end -local function use(t,fmt,...) - return t[fmt](...) -end -strings.formatters={} -if _LUAVERSION<5.2 then - function strings.formatters.new() - local t={ _extensions_={},_preamble_=preamble,_environment_={},_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end -else - function strings.formatters.new() - local e={} - for k,v in next,environment do - e[k]=v - end - local t={ _extensions_={},_preamble_="",_environment_=e,_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end -end -local formatters=strings.formatters.new() -string.formatters=formatters -string.formatter=function(str,...) return formatters[str](...) end -local function add(t,name,template,preamble) - if type(t)=="table" and t._type_=="formatter" then - t._extensions_[name]=template or "%s" - if type(preamble)=="string" then - t._preamble_=preamble.."\n"..t._preamble_ - elseif type(preamble)=="table" then - for k,v in next,preamble do - t._environment_[k]=v - end - end - end -end -strings.formatters.add=add -patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+P(1))^0) -patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) -patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) -patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) -if _LUAVERSION<5.2 then - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") -else - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape }) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-tab"] = package.loaded["util-tab"] or true - --- original size: 23980, stripped down to: 16119 - -if not modules then modules={} end modules ['util-tab']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utilities=utilities or {} -utilities.tables=utilities.tables or {} -local tables=utilities.tables -local format,gmatch,gsub,sub=string.format,string.gmatch,string.gsub,string.sub -local concat,insert,remove=table.concat,table.insert,table.remove -local setmetatable,getmetatable,tonumber,tostring=setmetatable,getmetatable,tonumber,tostring -local type,next,rawset,tonumber,tostring,load,select=type,next,rawset,tonumber,tostring,load,select -local lpegmatch,P,Cs,Cc=lpeg.match,lpeg.P,lpeg.Cs,lpeg.Cc -local sortedkeys,sortedpairs=table.sortedkeys,table.sortedpairs -local formatters=string.formatters -local utftoeight=utf.toeight -local splitter=lpeg.tsplitat(".") -function tables.definetable(target,nofirst,nolast) - local composed,shortcut,t=nil,nil,{} - local snippets=lpegmatch(splitter,target) - for i=1,#snippets-(nolast and 1 or 0) do - local name=snippets[i] - if composed then - composed=shortcut.."."..name - shortcut=shortcut.."_"..name - t[#t+1]=formatters["local %s = %s if not %s then %s = { } %s = %s end"](shortcut,composed,shortcut,shortcut,composed,shortcut) - else - composed=name - shortcut=name - if not nofirst then - t[#t+1]=formatters["%s = %s or { }"](composed,composed) - end - end - end - if nolast then - composed=shortcut.."."..snippets[#snippets] - end - return concat(t,"\n"),composed -end -function tables.definedtable(...) - local t=_G - for i=1,select("#",...) do - local li=select(i,...) - local tl=t[li] - if not tl then - tl={} - t[li]=tl - end - t=tl - end - return t -end -function tables.accesstable(target,root) - local t=root or _G - for name in gmatch(target,"([^%.]+)") do - t=t[name] - if not t then - return - end - end - return t -end -function tables.migratetable(target,v,root) - local t=root or _G - local names=string.split(target,".") - for i=1,#names-1 do - local name=names[i] - t[name]=t[name] or {} - t=t[name] - if not t then - return - end - end - t[names[#names]]=v -end -function tables.removevalue(t,value) - if value then - for i=1,#t do - if t[i]==value then - remove(t,i) - end - end - end -end -function tables.insertbeforevalue(t,value,extra) - for i=1,#t do - if t[i]==extra then - remove(t,i) - end - end - for i=1,#t do - if t[i]==value then - insert(t,i,extra) - return - end - end - insert(t,1,extra) -end -function tables.insertaftervalue(t,value,extra) - for i=1,#t do - if t[i]==extra then - remove(t,i) - end - end - for i=1,#t do - if t[i]==value then - insert(t,i+1,extra) - return - end - end - insert(t,#t+1,extra) -end -local escape=Cs(Cc('"')*((P('"')/'""'+P(1))^0)*Cc('"')) -function table.tocsv(t,specification) - if t and #t>0 then - local result={} - local r={} - specification=specification or {} - local fields=specification.fields - if type(fields)~="string" then - fields=sortedkeys(t[1]) - end - local separator=specification.separator or "," - if specification.preamble==true then - for f=1,#fields do - r[f]=lpegmatch(escape,tostring(fields[f])) - end - result[1]=concat(r,separator) - end - for i=1,#t do - local ti=t[i] - for f=1,#fields do - local field=ti[fields[f]] - if type(field)=="string" then - r[f]=lpegmatch(escape,field) - else - r[f]=tostring(field) - end - end - result[#result+1]=concat(r,separator) - end - return concat(result,"\n") - else - return "" - end -end -local nspaces=utilities.strings.newrepeater(" ") -local function toxml(t,d,result,step) - for k,v in sortedpairs(t) do - local s=nspaces[d] - local tk=type(k) - local tv=type(v) - if tv=="table" then - if tk=="number" then - result[#result+1]=formatters["%s<entry n='%s'>"](s,k) - toxml(v,d+step,result,step) - result[#result+1]=formatters["%s</entry>"](s,k) - else - result[#result+1]=formatters["%s<%s>"](s,k) - toxml(v,d+step,result,step) - result[#result+1]=formatters["%s</%s>"](s,k) - end - elseif tv=="string" then - if tk=="number" then - result[#result+1]=formatters["%s<entry n='%s'>%!xml!</entry>"](s,k,v,k) - else - result[#result+1]=formatters["%s<%s>%!xml!</%s>"](s,k,v,k) - end - elseif tk=="number" then - result[#result+1]=formatters["%s<entry n='%s'>%S</entry>"](s,k,v,k) - else - result[#result+1]=formatters["%s<%s>%S</%s>"](s,k,v,k) - end - end -end -function table.toxml(t,specification) - specification=specification or {} - local name=specification.name - local noroot=name==false - local result=(specification.nobanner or noroot) and {} or { "<?xml version='1.0' standalone='yes' ?>" } - local indent=specification.indent or 0 - local spaces=specification.spaces or 1 - if noroot then - toxml(t,indent,result,spaces) - else - toxml({ [name or "data"]=t },indent,result,spaces) - end - return concat(result,"\n") -end -function tables.encapsulate(core,capsule,protect) - if type(capsule)~="table" then - protect=true - capsule={} - end - for key,value in next,core do - if capsule[key] then - print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core)) - os.exit() - else - capsule[key]=value - end - end - if protect then - for key,value in next,core do - core[key]=nil - end - setmetatable(core,{ - __index=capsule, - __newindex=function(t,key,value) - if capsule[key] then - print(formatters["\ninvalid %s %a' in %a"]("overload",key,core)) - os.exit() - else - rawset(t,key,value) - end - end - } ) - end -end -local f_hashed_string=formatters["[%q]=%q,"] -local f_hashed_number=formatters["[%q]=%s,"] -local f_hashed_boolean=formatters["[%q]=%l,"] -local f_hashed_table=formatters["[%q]="] -local f_indexed_string=formatters["[%s]=%q,"] -local f_indexed_number=formatters["[%s]=%s,"] -local f_indexed_boolean=formatters["[%s]=%l,"] -local f_indexed_table=formatters["[%s]="] -local f_ordered_string=formatters["%q,"] -local f_ordered_number=formatters["%s,"] -local f_ordered_boolean=formatters["%l,"] -function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } - local m=1 - local function fastserialize(t,outer) - local n=#t - m=m+1 - r[m]="{" - if n>0 then - for i=0,n do - local v=t[i] - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_ordered_string(v) - elseif tv=="number" then - m=m+1 r[m]=f_ordered_number(v) - elseif tv=="table" then - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_ordered_boolean(v) - end - end - end - for k,v in next,t do - local tk=type(k) - if tk=="number" then - if k>n or k<0 then - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_indexed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(k,v) - end - end - else - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_hashed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_hashed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_hashed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_hashed_boolean(k,v) - end - end - end - m=m+1 - if outer then - r[m]="}" - else - r[m]="}," - end - return r - end - return concat(fastserialize(t,true)) -end -function table.deserialize(str) - if not str or str=="" then - return - end - local code=load(str) - if not code then - return - end - code=code() - if not code then - return - end - return code -end -function table.load(filename,loader) - if filename then - local t=(loader or io.loaddata)(filename) - if t and t~="" then - local t=utftoeight(t) - t=load(t) - if type(t)=="function" then - t=t() - if type(t)=="table" then - return t - end - end - end - end -end -function table.save(filename,t,n,...) - io.savedata(filename,table.serialize(t,n==nil and true or n,...)) -end -local f_key_value=formatters["%s=%q"] -local f_add_table=formatters[" {%t},\n"] -local f_return_table=formatters["return {\n%t}"] -local function slowdrop(t) - local r={} - local l={} - for i=1,#t do - local ti=t[i] - local j=0 - for k,v in next,ti do - j=j+1 - l[j]=f_key_value(k,v) - end - r[i]=f_add_table(l) - end - return f_return_table(r) -end -local function fastdrop(t) - local r={ "return {\n" } - local m=1 - for i=1,#t do - local ti=t[i] - m=m+1 r[m]=" {" - for k,v in next,ti do - m=m+1 r[m]=f_key_value(k,v) - end - m=m+1 r[m]="},\n" - end - m=m+1 - r[m]="}" - return concat(r) -end -function table.drop(t,slow) - if #t==0 then - return "return { }" - elseif slow==true then - return slowdrop(t) - else - return fastdrop(t) - end -end -function table.autokey(t,k) - local v={} - t[k]=v - return v -end -local selfmapper={ __index=function(t,k) t[k]=k return k end } -function table.twowaymapper(t) - if not t then - t={} - else - for i=0,#t do - local ti=t[i] - if ti then - local i=tostring(i) - t[i]=ti - t[ti]=i - end - end - t[""]=t[0] or "" - end - setmetatable(t,selfmapper) - return t -end -local f_start_key_idx=formatters["%w{"] -local f_start_key_num=formatters["%w[%s]={"] -local f_start_key_str=formatters["%w[%q]={"] -local f_start_key_boo=formatters["%w[%l]={"] -local f_start_key_nop=formatters["%w{"] -local f_stop=formatters["%w},"] -local f_key_num_value_num=formatters["%w[%s]=%s,"] -local f_key_str_value_num=formatters["%w[%q]=%s,"] -local f_key_boo_value_num=formatters["%w[%l]=%s,"] -local f_key_num_value_str=formatters["%w[%s]=%q,"] -local f_key_str_value_str=formatters["%w[%q]=%q,"] -local f_key_boo_value_str=formatters["%w[%l]=%q,"] -local f_key_num_value_boo=formatters["%w[%s]=%l,"] -local f_key_str_value_boo=formatters["%w[%q]=%l,"] -local f_key_boo_value_boo=formatters["%w[%l]=%l,"] -local f_key_num_value_not=formatters["%w[%s]={},"] -local f_key_str_value_not=formatters["%w[%q]={},"] -local f_key_boo_value_not=formatters["%w[%l]={},"] -local f_key_num_value_seq=formatters["%w[%s]={ %, t },"] -local f_key_str_value_seq=formatters["%w[%q]={ %, t },"] -local f_key_boo_value_seq=formatters["%w[%l]={ %, t },"] -local f_val_num=formatters["%w%s,"] -local f_val_str=formatters["%w%q,"] -local f_val_boo=formatters["%w%l,"] -local f_val_not=formatters["%w{},"] -local f_val_seq=formatters["%w{ %, t },"] -local f_table_return=formatters["return {"] -local f_table_name=formatters["%s={"] -local f_table_direct=formatters["{"] -local f_table_entry=formatters["[%q]={"] -local f_table_finish=formatters["}"] -local spaces=utilities.strings.newrepeater(" ") -local serialize=table.serialize -function table.serialize(root,name,specification) - if type(specification)=="table" then - return serialize(root,name,specification) - end - local t - local n=1 - local function simple_table(t) - if #t>0 then - local n=0 - for _,v in next,t do - n=n+1 - if type(v)=="table" then - return nil - end - end - if n==#t then - local tt={} - local nt=0 - for i=1,#t do - local v=t[i] - local tv=type(v) - nt=nt+1 - if tv=="number" then - tt[nt]=v - elseif tv=="string" then - tt[nt]=format("%q",v) - elseif tv=="boolean" then - tt[nt]=v and "true" or "false" - else - return nil - end - end - return tt - end - end - return nil - end - local function do_serialize(root,name,depth,level,indexed) - if level>0 then - n=n+1 - if indexed then - t[n]=f_start_key_idx(depth) - else - local tn=type(name) - if tn=="number" then - t[n]=f_start_key_num(depth,name) - elseif tn=="string" then - t[n]=f_start_key_str(depth,name) - elseif tn=="boolean" then - t[n]=f_start_key_boo(depth,name) - else - t[n]=f_start_key_nop(depth) - end - end - depth=depth+1 - end - if root and next(root) then - local first=nil - local last=0 - last=#root - for k=1,last do - if root[k]==nil then - last=k-1 - break - end - end - if last>0 then - first=1 - end - local sk=sortedkeys(root) - for i=1,#sk do - local k=sk[i] - local v=root[k] - local tv=type(v) - local tk=type(k) - if first and tk=="number" and k>=first and k<=last then - if tv=="number" then - n=n+1 t[n]=f_val_num(depth,v) - elseif tv=="string" then - n=n+1 t[n]=f_val_str(depth,v) - elseif tv=="table" then - if not next(v) then - n=n+1 t[n]=f_val_not(depth) - else - local st=simple_table(v) - if st then - n=n+1 t[n]=f_val_seq(depth,st) - else - do_serialize(v,k,depth,level+1,true) - end - end - elseif tv=="boolean" then - n=n+1 t[n]=f_val_boo(depth,v) - end - elseif tv=="number" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_num(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_num(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_num(depth,k,v) - end - elseif tv=="string" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_str(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_str(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_str(depth,k,v) - end - elseif tv=="table" then - if not next(v) then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_not(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_not(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_not(depth,k,v) - end - else - local st=simple_table(v) - if not st then - do_serialize(v,k,depth,level+1) - elseif tk=="number" then - n=n+1 t[n]=f_key_num_value_seq(depth,k,st) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_seq(depth,k,st) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_seq(depth,k,st) - end - end - elseif tv=="boolean" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_boo(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_boo(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_boo(depth,k,v) - end - end - end - end - if level>0 then - n=n+1 t[n]=f_stop(depth-1) - end - end - local tname=type(name) - if tname=="string" then - if name=="return" then - t={ f_table_return() } - else - t={ f_table_name(name) } - end - elseif tname=="number" then - t={ f_table_entry(name) } - elseif tname=="boolean" then - if name then - t={ f_table_return() } - else - t={ f_table_direct() } - end - else - t={ f_table_name("t") } - end - if root then - if getmetatable(root) then - local dummy=root._w_h_a_t_e_v_e_r_ - root._w_h_a_t_e_v_e_r_=nil - end - if next(root) then - do_serialize(root,name,1,0) - end - end - n=n+1 - t[n]=f_table_finish() - return concat(t,"\n") -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-sto"] = package.loaded["util-sto"] or true - --- original size: 4172, stripped down to: 2953 - -if not modules then modules={} end modules ['util-sto']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local setmetatable,getmetatable,type=setmetatable,getmetatable,type -utilities=utilities or {} -utilities.storage=utilities.storage or {} -local storage=utilities.storage -function storage.mark(t) - if not t then - print("\nfatal error: storage cannot be marked\n") - os.exit() - return - end - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m.__storage__=true - return t -end -function storage.allocate(t) - t=t or {} - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m.__storage__=true - return t -end -function storage.marked(t) - local m=getmetatable(t) - return m and m.__storage__ -end -function storage.checked(t) - if not t then - report("\nfatal error: storage has not been allocated\n") - os.exit() - return - end - return t -end -function storage.setinitializer(data,initialize) - local m=getmetatable(data) or {} - m.__index=function(data,k) - m.__index=nil - initialize() - return data[k] - end - setmetatable(data,m) -end -local keyisvalue={ __index=function(t,k) - t[k]=k - return k -end } -function storage.sparse(t) - t=t or {} - setmetatable(t,keyisvalue) - return t -end -local function f_empty () return "" end -local function f_self (t,k) t[k]=k return k end -local function f_table (t,k) local v={} t[k]=v return v end -local function f_number(t,k) t[k]=0 return 0 end -local function f_ignore() end -local f_index={ - ["empty"]=f_empty, - ["self"]=f_self, - ["table"]=f_table, - ["number"]=f_number, -} -local t_index={ - ["empty"]={ __index=f_empty }, - ["self"]={ __index=f_self }, - ["table"]={ __index=f_table }, - ["number"]={ __index=f_number }, -} -function table.setmetatableindex(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - if m then - m.__index=f_index[f] or f - else - setmetatable(t,t_index[f] or { __index=f }) - end - return t -end -local f_index={ - ["ignore"]=f_ignore, -} -local t_index={ - ["ignore"]={ __newindex=f_ignore }, -} -function table.setmetatablenewindex(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - if m then - m.__newindex=f_index[f] or f - else - setmetatable(t,t_index[f] or { __newindex=f }) - end - return t -end -function table.setmetatablecall(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - if m then - m.__call=f - else - setmetatable(t,{ __call=f }) - end - return t -end -function table.setmetatablekey(t,key,value) - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m[key]=value - return t -end -function table.getmetatablekey(t,key,value) - local m=getmetatable(t) - return m and m[key] -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-prs"] = package.loaded["util-prs"] or true - --- original size: 19604, stripped down to: 13998 - -if not modules then modules={} end modules ['util-prs']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local lpeg,table,string=lpeg,table,string -local P,R,V,S,C,Ct,Cs,Carg,Cc,Cg,Cf,Cp=lpeg.P,lpeg.R,lpeg.V,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cc,lpeg.Cg,lpeg.Cf,lpeg.Cp -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local concat,gmatch,find=table.concat,string.gmatch,string.find -local tostring,type,next,rawset=tostring,type,next,rawset -local mod,div=math.mod,math.div -utilities=utilities or {} -local parsers=utilities.parsers or {} -utilities.parsers=parsers -local patterns=parsers.patterns or {} -parsers.patterns=patterns -local setmetatableindex=table.setmetatableindex -local sortedhash=table.sortedhash -local digit=R("09") -local space=P(' ') -local equal=P("=") -local comma=P(",") -local lbrace=P("{") -local rbrace=P("}") -local lparent=P("(") -local rparent=P(")") -local period=S(".") -local punctuation=S(".,:;") -local spacer=lpegpatterns.spacer -local whitespace=lpegpatterns.whitespace -local newline=lpegpatterns.newline -local anything=lpegpatterns.anything -local endofstring=lpegpatterns.endofstring -local nobrace=1-(lbrace+rbrace ) -local noparent=1-(lparent+rparent) -local escape,left,right=P("\\"),P('{'),P('}') -lpegpatterns.balanced=P { - [1]=((escape*(left+right))+(1-(left+right))+V(2))^0, - [2]=left*V(1)*right -} -local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } -local nestedparents=P { lparent*(noparent+V(1))^0*rparent } -local spaces=space^0 -local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/"")) -local content=(1-endofstring)^0 -lpegpatterns.nestedbraces=nestedbraces -lpegpatterns.nestedparents=nestedparents -lpegpatterns.nested=nestedbraces -lpegpatterns.argument=argument -lpegpatterns.content=content -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0) -local key=C((1-equal-comma)^1) -local pattern_a=(space+comma)^0*(key*equal*value+key*C("")) -local pattern_c=(space+comma)^0*(key*equal*value) -local key=C((1-space-equal-comma)^1) -local pattern_b=spaces*comma^0*spaces*(key*((spaces*equal*spaces*value)+C(""))) -local hash={} -local function set(key,value) - hash[key]=value -end -local pattern_a_s=(pattern_a/set)^1 -local pattern_b_s=(pattern_b/set)^1 -local pattern_c_s=(pattern_c/set)^1 -patterns.settings_to_hash_a=pattern_a_s -patterns.settings_to_hash_b=pattern_b_s -patterns.settings_to_hash_c=pattern_c_s -function parsers.make_settings_to_hash_pattern(set,how) - if type(str)=="table" then - return set - elseif how=="strict" then - return (pattern_c/set)^1 - elseif how=="tolerant" then - return (pattern_b/set)^1 - else - return (pattern_a/set)^1 - end -end -function parsers.settings_to_hash(str,existing) - if type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - elseif str and str~="" then - hash=existing or {} - lpegmatch(pattern_a_s,str) - return hash - else - return {} - end -end -function parsers.settings_to_hash_tolerant(str,existing) - if type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - elseif str and str~="" then - hash=existing or {} - lpegmatch(pattern_b_s,str) - return hash - else - return {} - end -end -function parsers.settings_to_hash_strict(str,existing) - if type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - elseif str and str~="" then - hash=existing or {} - lpegmatch(pattern_c_s,str) - return next(hash) and hash - else - return nil - end -end -local separator=comma*space^0 -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-comma))^0) -local pattern=spaces*Ct(value*(separator*value)^0) -patterns.settings_to_array=pattern -function parsers.settings_to_array(str,strict) - if type(str)=="table" then - return str - elseif not str or str=="" then - return {} - elseif strict then - if find(str,"{") then - return lpegmatch(pattern,str) - else - return { str } - end - elseif find(str,",") then - return lpegmatch(pattern,str) - else - return { str } - end -end -local separator=space^0*comma*space^0 -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-(space^0*(comma+P(-1)))))^0) -local withvalue=Carg(1)*value/function(f,s) return f(s) end -local pattern_a=spaces*Ct(value*(separator*value)^0) -local pattern_b=spaces*withvalue*(separator*withvalue)^0 -function parsers.stripped_settings_to_array(str) - if not str or str=="" then - return {} - else - return lpegmatch(pattern_a,str) - end -end -function parsers.process_stripped_settings(str,action) - if not str or str=="" then - return {} - else - return lpegmatch(pattern_b,str,1,action) - end -end -local function set(t,v) - t[#t+1]=v -end -local value=P(Carg(1)*value)/set -local pattern=value*(separator*value)^0*Carg(1) -function parsers.add_settings_to_array(t,str) - return lpegmatch(pattern,str,nil,t) -end -function parsers.hash_to_string(h,separator,yes,no,strict,omit) - if h then - local t,tn,s={},0,table.sortedkeys(h) - omit=omit and table.tohash(omit) - for i=1,#s do - local key=s[i] - if not omit or not omit[key] then - local value=h[key] - if type(value)=="boolean" then - if yes and no then - if value then - tn=tn+1 - t[tn]=key..'='..yes - elseif not strict then - tn=tn+1 - t[tn]=key..'='..no - end - elseif value or not strict then - tn=tn+1 - t[tn]=key..'='..tostring(value) - end - else - tn=tn+1 - t[tn]=key..'='..value - end - end - end - return concat(t,separator or ",") - else - return "" - end -end -function parsers.array_to_string(a,separator) - if a then - return concat(a,separator or ",") - else - return "" - end -end -function parsers.settings_to_set(str,t) - t=t or {} - for s in gmatch(str,"[^, ]+") do - t[s]=true - end - return t -end -function parsers.simple_hash_to_string(h,separator) - local t,tn={},0 - for k,v in sortedhash(h) do - if v then - tn=tn+1 - t[tn]=k - end - end - return concat(t,separator or ",") -end -local str=C((1-whitespace-equal)^1) -local setting=Cf(Carg(1)*(whitespace^0*Cg(str*whitespace^0*(equal*whitespace^0*str+Cc(""))))^1,rawset) -local splitter=setting^1 -function utilities.parsers.options_to_hash(str,target) - return str and lpegmatch(splitter,str,1,target or {}) or {} -end -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1) -local pattern_a=spaces*Ct(value*(separator*value)^0) -local function repeater(n,str) - if not n then - return str - else - local s=lpegmatch(pattern_a,str) - if n==1 then - return unpack(s) - else - local t,tn={},0 - for i=1,n do - for j=1,#s do - tn=tn+1 - t[tn]=s[j] - end - end - return unpack(t) - end - end -end -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+(C(digit^1)/tonumber*lparent*Cs((noparent+nestedparents)^1)*rparent)/repeater+C((nestedbraces+(1-comma))^1) -local pattern_b=spaces*Ct(value*(separator*value)^0) -function parsers.settings_to_array_with_repeat(str,expand) - if expand then - return lpegmatch(pattern_b,str) or {} - else - return lpegmatch(pattern_a,str) or {} - end -end -local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace -local pattern=Ct((space+value)^0) -function parsers.arguments_to_table(str) - return lpegmatch(pattern,str) -end -function parsers.getparameters(self,class,parentclass,settings) - local sc=self[class] - if not sc then - sc={} - self[class]=sc - if parentclass then - local sp=self[parentclass] - if not sp then - sp={} - self[parentclass]=sp - end - setmetatableindex(sc,sp) - end - end - parsers.settings_to_hash(settings,sc) -end -function parsers.listitem(str) - return gmatch(str,"[^, ]+") -end -local pattern=Cs { "start", - start=V("one")+V("two")+V("three"), - rest=(Cc(",")*V("thousand"))^0*(P(".")+endofstring)*anything^0, - thousand=digit*digit*digit, - one=digit*V("rest"), - two=digit*digit*V("rest"), - three=V("thousand")*V("rest"), -} -lpegpatterns.splitthousands=pattern -function parsers.splitthousands(str) - return lpegmatch(pattern,str) or str -end -local optionalwhitespace=whitespace^0 -lpegpatterns.words=Ct((Cs((1-punctuation-whitespace)^1)+anything)^1) -lpegpatterns.sentences=Ct((optionalwhitespace*Cs((1-period)^0*period))^1) -lpegpatterns.paragraphs=Ct((optionalwhitespace*Cs((whitespace^1*endofstring/""+1-(spacer^0*newline*newline))^1))^1) -local dquote=P('"') -local equal=P('=') -local escape=P('\\') -local separator=S(' ,') -local key=C((1-equal)^1) -local value=dquote*C((1-dquote-escape*dquote)^0)*dquote -local pattern=Cf(Ct("")*(Cg(key*equal*value)*separator^0)^1,rawset)^0*P(-1) -function parsers.keq_to_hash(str) - if str and str~="" then - return lpegmatch(pattern,str) - else - return {} - end -end -local defaultspecification={ separator=",",quote='"' } -function parsers.csvsplitter(specification) - specification=specification and table.setmetatableindex(specification,defaultspecification) or defaultspecification - local separator=specification.separator - local quotechar=specification.quote - local separator=S(separator~="" and separator or ",") - local whatever=C((1-separator-newline)^0) - if quotechar and quotechar~="" then - local quotedata=nil - for chr in gmatch(quotechar,".") do - local quotechar=P(chr) - local quoteword=quotechar*C((1-quotechar)^0)*quotechar - if quotedata then - quotedata=quotedata+quoteword - else - quotedata=quoteword - end - end - whatever=quotedata+whatever - end - local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r")^1)^0 ) - return function(data) - return lpegmatch(parser,data) - end -end -function parsers.rfc4180splitter(specification) - specification=specification and table.setmetatableindex(specification,defaultspecification) or defaultspecification - local separator=specification.separator - local quotechar=P(specification.quote) - local dquotechar=quotechar*quotechar -/specification.quote - local separator=S(separator~="" and separator or ",") - local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*quotechar - local non_escaped=C((1-quotechar-newline-separator)^1) - local field=escaped+non_escaped+Cc("") - local record=Ct(field*(separator*field)^1) - local headerline=record*Cp() - local wholeblob=Ct((newline^-1*record)^0) - return function(data,getheader) - if getheader then - local header,position=lpegmatch(headerline,data) - local data=lpegmatch(wholeblob,data,position) - return data,header - else - return lpegmatch(wholeblob,data) - end - end -end -local function ranger(first,last,n,action) - if not first then - elseif last==true then - for i=first,n or first do - action(i) - end - elseif last then - for i=first,last do - action(i) - end - else - action(first) - end -end -local cardinal=lpegpatterns.cardinal/tonumber -local spacers=lpegpatterns.spacer^0 -local endofstring=lpegpatterns.endofstring -local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1 -local stepper=spacers*(C(cardinal)*(spacers*S(":-")*spacers*(C(cardinal)+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring -function parsers.stepper(str,n,action) - if type(n)=="function" then - lpegmatch(stepper,str,1,false,n or print) - else - lpegmatch(stepper,str,1,n,action or print) - end -end -local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0) -local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0) -patterns.unittotex=pattern -function parsers.unittotex(str,textmode) - return lpegmatch(textmode and pattern_text or pattern_math,str) -end -local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+P(1))^0) -function parsers.unittoxml(str) - return lpegmatch(pattern,str) -end -local cache={} -local spaces=lpeg.patterns.space^0 -local dummy=function() end -table.setmetatableindex(cache,function(t,k) - local separator=P(k) - local value=(1-separator)^0 - local pattern=spaces*C(value)*separator^0*Cp() - t[k]=pattern - return pattern -end) -local commalistiterator=cache[","] -function utilities.parsers.iterator(str,separator) - local n=#str - if n==0 then - return dummy - else - local pattern=separator and cache[separator] or commalistiterator - local p=1 - return function() - if p<=n then - local s,e=lpegmatch(pattern,str,p) - if e then - p=e - return s - end - end - end - end -end -local function initialize(t,name) - local source=t[name] - if source then - local result={} - for k,v in next,t[name] do - result[k]=v - end - return result - else - return {} - end -end -local function fetch(t,name) - return t[name] or {} -end -local function process(result,more) - for k,v in next,more do - result[k]=v - end - return result -end -local name=C((1-S(", "))^1) -local parser=(Carg(1)*name/initialize)*(S(", ")^1*(Carg(1)*name/fetch))^0 -local merge=Cf(parser,process) -function utilities.parsers.mergehashes(hash,list) - return lpegmatch(merge,list,1,hash) -end -function utilities.parsers.runtime(time) - if not time then - time=os.runtime() - end - local days=div(time,24*60*60) - time=mod(time,24*60*60) - local hours=div(time,60*60) - time=mod(time,60*60) - local minutes=div(time,60) - local seconds=mod(time,60) - return days,hours,minutes,seconds -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-fmt"] = package.loaded["util-fmt"] or true - --- original size: 2274, stripped down to: 1781 - -if not modules then modules={} end modules ['util-fmt']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utilities=utilities or {} -utilities.formatters=utilities.formatters or {} -local formatters=utilities.formatters -local concat,format=table.concat,string.format -local tostring,type=tostring,type -local strip=string.strip -local lpegmatch=lpeg.match -local stripper=lpeg.patterns.stripzeros -function formatters.stripzeros(str) - return lpegmatch(stripper,str) -end -function formatters.formatcolumns(result,between) - if result and #result>0 then - between=between or " " - local widths,numbers={},{} - local first=result[1] - local n=#first - for i=1,n do - widths[i]=0 - end - for i=1,#result do - local r=result[i] - for j=1,n do - local rj=r[j] - local tj=type(rj) - if tj=="number" then - numbers[j]=true - end - if tj~="string" then - rj=tostring(rj) - r[j]=rj - end - local w=#rj - if w>widths[j] then - widths[j]=w - end - end - end - for i=1,n do - local w=widths[i] - if numbers[i] then - if w>80 then - widths[i]="%s"..between - else - widths[i]="%0"..w.."i"..between - end - else - if w>80 then - widths[i]="%s"..between - elseif w>0 then - widths[i]="%-"..w.."s"..between - else - widths[i]="%s" - end - end - end - local template=strip(concat(widths)) - for i=1,#result do - local str=format(template,unpack(result[i])) - result[i]=strip(str) - end - end - return result -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-set"] = package.loaded["trac-set"] or true - --- original size: 12365, stripped down to: 8799 - -if not modules then modules={} end modules ['trac-set']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,next,tostring=type,next,tostring -local concat=table.concat -local format,find,lower,gsub,topattern=string.format,string.find,string.lower,string.gsub,string.topattern -local is_boolean=string.is_boolean -local settings_to_hash=utilities.parsers.settings_to_hash -local allocate=utilities.storage.allocate -utilities=utilities or {} -local utilities=utilities -local setters=utilities.setters or {} -utilities.setters=setters -local data={} -local trace_initialize=false -function setters.initialize(filename,name,values) - local setter=data[name] - if setter then - frozen=true - local data=setter.data - if data then - for key,newvalue in next,values do - local newvalue=is_boolean(newvalue,newvalue) - local functions=data[key] - if functions then - local oldvalue=functions.value - if functions.frozen then - if trace_initialize then - setter.report("%s: %a is %s to %a",filename,key,"frozen",oldvalue) - end - elseif #functions>0 and not oldvalue then - if trace_initialize then - setter.report("%s: %a is %s to %a",filename,key,"set",newvalue) - end - for i=1,#functions do - functions[i](newvalue) - end - functions.value=newvalue - functions.frozen=functions.frozen or frozen - else - if trace_initialize then - setter.report("%s: %a is %s as %a",filename,key,"kept",oldvalue) - end - end - else - functions={ default=newvalue,frozen=frozen } - data[key]=functions - if trace_initialize then - setter.report("%s: %a is %s to %a",filename,key,"defaulted",newvalue) - end - end - end - return true - end - end -end -local function set(t,what,newvalue) - local data=t.data - if not data.frozen then - local done=t.done - if type(what)=="string" then - what=settings_to_hash(what) - end - if type(what)~="table" then - return - end - if not done then - done={} - t.done=done - end - for w,value in next,what do - if value=="" then - value=newvalue - elseif not value then - value=false - else - value=is_boolean(value,value) - end - w=topattern(w,true,true) - for name,functions in next,data do - if done[name] then - elseif find(name,w) then - done[name]=true - for i=1,#functions do - functions[i](value) - end - functions.value=value - end - end - end - end -end -local function reset(t) - local data=t.data - if not data.frozen then - for name,functions in next,data do - for i=1,#functions do - functions[i](false) - end - functions.value=false - end - end -end -local function enable(t,what) - set(t,what,true) -end -local function disable(t,what) - local data=t.data - if not what or what=="" then - t.done={} - reset(t) - else - set(t,what,false) - end -end -function setters.register(t,what,...) - local data=t.data - what=lower(what) - local functions=data[what] - if not functions then - functions={} - data[what]=functions - if trace_initialize then - t.report("defining %a",what) - end - end - local default=functions.default - for i=1,select("#",...) do - local fnc=select(i,...) - local typ=type(fnc) - if typ=="string" then - if trace_initialize then - t.report("coupling %a to %a",what,fnc) - end - local s=fnc - fnc=function(value) set(t,s,value) end - elseif typ~="function" then - fnc=nil - end - if fnc then - functions[#functions+1]=fnc - local value=functions.value or default - if value~=nil then - fnc(value) - functions.value=value - end - end - end - return false -end -function setters.enable(t,what) - local e=t.enable - t.enable,t.done=enable,{} - enable(t,what) - t.enable,t.done=e,{} -end -function setters.disable(t,what) - local e=t.disable - t.disable,t.done=disable,{} - disable(t,what) - t.disable,t.done=e,{} -end -function setters.reset(t) - t.done={} - reset(t) -end -function setters.list(t) - local list=table.sortedkeys(t.data) - local user,system={},{} - for l=1,#list do - local what=list[l] - if find(what,"^%*") then - system[#system+1]=what - else - user[#user+1]=what - end - end - return user,system -end -function setters.show(t) - local category=t.name - local list=setters.list(t) - t.report() - for k=1,#list do - local name=list[k] - local functions=t.data[name] - if functions then - local value,default,modules=functions.value,functions.default,#functions - value=value==nil and "unset" or tostring(value) - default=default==nil and "unset" or tostring(default) - t.report("%-50s modules: %2i default: %-12s value: %-12s",name,modules,default,value) - end - end - t.report() -end -local enable,disable,register,list,show=setters.enable,setters.disable,setters.register,setters.list,setters.show -function setters.report(setter,...) - print(format("%-15s : %s\n",setter.name,format(...))) -end -local function default(setter,name) - local d=setter.data[name] - return d and d.default -end -local function value(setter,name) - local d=setter.data[name] - return d and (d.value or d.default) -end -function setters.new(name) - local setter - setter={ - data=allocate(), - name=name, - report=function(...) setters.report (setter,...) end, - enable=function(...) enable (setter,...) end, - disable=function(...) disable (setter,...) end, - register=function(...) register(setter,...) end, - list=function(...) list (setter,...) end, - show=function(...) show (setter,...) end, - default=function(...) return default (setter,...) end, - value=function(...) return value (setter,...) end, - } - data[name]=setter - return setter -end -trackers=setters.new("trackers") -directives=setters.new("directives") -experiments=setters.new("experiments") -local t_enable,t_disable=trackers .enable,trackers .disable -local d_enable,d_disable=directives .enable,directives .disable -local e_enable,e_disable=experiments.enable,experiments.disable -local trace_directives=false local trace_directives=false trackers.register("system.directives",function(v) trace_directives=v end) -local trace_experiments=false local trace_experiments=false trackers.register("system.experiments",function(v) trace_experiments=v end) -function directives.enable(...) - if trace_directives then - directives.report("enabling: % t",{...}) - end - d_enable(...) -end -function directives.disable(...) - if trace_directives then - directives.report("disabling: % t",{...}) - end - d_disable(...) -end -function experiments.enable(...) - if trace_experiments then - experiments.report("enabling: % t",{...}) - end - e_enable(...) -end -function experiments.disable(...) - if trace_experiments then - experiments.report("disabling: % t",{...}) - end - e_disable(...) -end -directives.register("system.nostatistics",function(v) - if statistics then - statistics.enable=not v - else - end -end) -directives.register("system.nolibraries",function(v) - if libraries then - libraries=nil - else - end -end) -if environment then - local engineflags=environment.engineflags - if engineflags then - local list=engineflags["c:trackers"] or engineflags["trackers"] - if type(list)=="string" then - setters.initialize("commandline flags","trackers",settings_to_hash(list)) - end - local list=engineflags["c:directives"] or engineflags["directives"] - if type(list)=="string" then - setters.initialize("commandline flags","directives",settings_to_hash(list)) - end - end -end -if texconfig then - local function set(k,v) - v=tonumber(v) - if v then - texconfig[k]=v - end - end - directives.register("luatex.expanddepth",function(v) set("expand_depth",v) end) - directives.register("luatex.hashextra",function(v) set("hash_extra",v) end) - directives.register("luatex.nestsize",function(v) set("nest_size",v) end) - directives.register("luatex.maxinopen",function(v) set("max_in_open",v) end) - directives.register("luatex.maxprintline",function(v) set("max_print_line",v) end) - directives.register("luatex.maxstrings",function(v) set("max_strings",v) end) - directives.register("luatex.paramsize",function(v) set("param_size",v) end) - directives.register("luatex.savesize",function(v) set("save_size",v) end) - directives.register("luatex.stacksize",function(v) set("stack_size",v) end) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-log"] = package.loaded["trac-log"] or true - --- original size: 25391, stripped down to: 16561 - -if not modules then modules={} end modules ['trac-log']={ - version=1.001, - comment="companion to trac-log.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local write_nl,write=texio and texio.write_nl or print,texio and texio.write or io.write -local format,gmatch,find=string.format,string.gmatch,string.find -local concat,insert,remove=table.concat,table.insert,table.remove -local topattern=string.topattern -local next,type,select=next,type,select -local utfchar=utf.char -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local texgetcount=tex and tex.getcount -logs=logs or {} -local logs=logs -local moreinfo=[[ -More information about ConTeXt and the tools that come with it can be found at: -]].."\n"..[[ -maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context -webpage : http://www.pragma-ade.nl / http://tex.aanhet.net -wiki : http://contextgarden.net -]] -utilities.strings.formatters.add ( - formatters,"unichr", - [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]] -) -utilities.strings.formatters.add ( - formatters,"chruni", - [[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]] -) -local function ignore() end -setmetatableindex(logs,function(t,k) t[k]=ignore;return ignore end) -local report,subreport,status,settarget,setformats,settranslations -local direct,subdirect,writer,pushtarget,poptarget,setlogfile,settimedlog,setprocessor,setformatters -if tex and (tex.jobname or tex.formatname) then - local valueiskey={ __index=function(t,k) t[k]=k return k end } - local target="term and log" - logs.flush=io.flush - local formats={} setmetatable(formats,valueiskey) - local translations={} setmetatable(translations,valueiskey) - writer=function(...) - write_nl(target,...) - end - newline=function() - write_nl(target,"\n") - end - local report_yes=formatters["%-15s > %s\n"] - local report_nop=formatters["%-15s >\n"] - report=function(a,b,c,...) - if c then - write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,report_yes(translations[a],formats[b])) - elseif a then - write_nl(target,report_nop(translations[a])) - else - write_nl(target,"\n") - end - end - local direct_yes=formatters["%-15s > %s"] - local direct_nop=formatters["%-15s >"] - direct=function(a,b,c,...) - if c then - return direct_yes(translations[a],formatters[formats[b]](c,...)) - elseif b then - return direct_yes(translations[a],formats[b]) - elseif a then - return direct_nop(translations[a]) - else - return "" - end - end - local subreport_yes=formatters["%-15s > %s > %s\n"] - local subreport_nop=formatters["%-15s > %s >\n"] - subreport=function(a,s,b,c,...) - if c then - write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,subreport_yes(translations[a],translations[s],formats[b])) - elseif a then - write_nl(target,subreport_nop(translations[a],translations[s])) - else - write_nl(target,"\n") - end - end - local subdirect_yes=formatters["%-15s > %s > %s"] - local subdirect_nop=formatters["%-15s > %s >"] - subdirect=function(a,s,b,c,...) - if c then - return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...)) - elseif b then - return subdirect_yes(translations[a],translations[s],formats[b]) - elseif a then - return subdirect_nop(translations[a],translations[s]) - else - return "" - end - end - local status_yes=formatters["%-15s : %s\n"] - local status_nop=formatters["%-15s :\n"] - status=function(a,b,c,...) - if c then - write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...))) - elseif b then - write_nl(target,status_yes(translations[a],formats[b])) - elseif a then - write_nl(target,status_nop(translations[a])) - else - write_nl(target,"\n") - end - end - local targets={ - logfile="log", - log="log", - file="log", - console="term", - terminal="term", - both="term and log", - } - settarget=function(whereto) - target=targets[whereto or "both"] or targets.both - if target=="term" or target=="term and log" then - logs.flush=io.flush - else - logs.flush=ignore - end - end - local stack={} - pushtarget=function(newtarget) - insert(stack,target) - settarget(newtarget) - end - poptarget=function() - if #stack>0 then - settarget(remove(stack)) - end - end - setformats=function(f) - formats=f - end - settranslations=function(t) - translations=t - end - setprocessor=function(f) - local writeline=write_nl - write_nl=function(target,...) - writeline(target,f(...)) - end - end - setformatters=function(f) - report_yes=f.report_yes or report_yes - report_nop=f.report_nop or report_nop - subreport_yes=f.subreport_yes or subreport_yes - subreport_nop=f.subreport_nop or subreport_nop - direct_yes=f.direct_yes or direct_yes - direct_nop=f.direct_nop or direct_nop - subdirect_yes=f.subdirect_yes or subdirect_yes - subdirect_nop=f.subdirect_nop or subdirect_nop - status_yes=f.status_yes or status_yes - status_nop=f.status_nop or status_nop - end - setlogfile=ignore - settimedlog=ignore -else - logs.flush=ignore - writer=function(s) - write_nl(s) - end - newline=function() - write_nl("\n") - end - local report_yes=formatters["%-15s | %s"] - local report_nop=formatters["%-15s |"] - report=function(a,b,c,...) - if c then - write_nl(report_yes(a,formatters[b](c,...))) - elseif b then - write_nl(report_yes(a,b)) - elseif a then - write_nl(report_nop(a)) - else - write_nl("") - end - end - local subreport_yes=formatters["%-15s | %s | %s"] - local subreport_nop=formatters["%-15s | %s |"] - subreport=function(a,sub,b,c,...) - if c then - write_nl(subreport_yes(a,sub,formatters[b](c,...))) - elseif b then - write_nl(subreport_yes(a,sub,b)) - elseif a then - write_nl(subreport_nop(a,sub)) - else - write_nl("") - end - end - local status_yes=formatters["%-15s : %s\n"] - local status_nop=formatters["%-15s :\n"] - status=function(a,b,c,...) - if c then - write_nl(status_yes(a,formatters[b](c,...))) - elseif b then - write_nl(status_yes(a,b)) - elseif a then - write_nl(status_nop(a)) - else - write_nl("\n") - end - end - direct=ignore - subdirect=ignore - settarget=ignore - pushtarget=ignore - poptarget=ignore - setformats=ignore - settranslations=ignore - setprocessor=function(f) - local writeline=write_nl - write_nl=function(s) - writeline(f(s)) - end - end - setformatters=function(f) - report_yes=f.report_yes or report_yes - report_nop=f.report_nop or report_nop - subreport_yes=f.subreport_yes or subreport_yes - subreport_nop=f.subreport_nop or subreport_nop - status_yes=f.status_yes or status_yes - status_nop=f.status_nop or status_nop - end - setlogfile=function(name,keepopen) - if name and name~="" then - local localtime=os.localtime - local writeline=write_nl - if keepopen then - local f=io.open(name,"ab") - write_nl=function(s) - writeline(s) - f:write(localtime()," | ",s,"\n") - end - else - write_nl=function(s) - writeline(s) - local f=io.open(name,"ab") - f:write(localtime()," | ",s,"\n") - f:close() - end - end - end - setlogfile=ignore - end - settimedlog=function() - local localtime=os.localtime - local writeline=write_nl - write_nl=function(s) - writeline(localtime().." | "..s) - end - settimedlog=ignore - end -end -logs.report=report -logs.subreport=subreport -logs.status=status -logs.settarget=settarget -logs.pushtarget=pushtarget -logs.poptarget=poptarget -logs.setformats=setformats -logs.settranslations=settranslations -logs.setlogfile=setlogfile -logs.settimedlog=settimedlog -logs.setprocessor=setprocessor -logs.setformatters=setformatters -logs.direct=direct -logs.subdirect=subdirect -logs.writer=writer -logs.newline=newline -local data,states={},nil -function logs.reporter(category,subcategory) - local logger=data[category] - if not logger then - local state=false - if states==true then - state=true - elseif type(states)=="table" then - for c,_ in next,states do - if find(category,c) then - state=true - break - end - end - end - logger={ - reporters={}, - state=state, - } - data[category]=logger - end - local reporter=logger.reporters[subcategory or "default"] - if not reporter then - if subcategory then - reporter=function(...) - if not logger.state then - subreport(category,subcategory,...) - end - end - logger.reporters[subcategory]=reporter - else - local tag=category - reporter=function(...) - if not logger.state then - report(category,...) - end - end - logger.reporters.default=reporter - end - end - return reporter -end -logs.new=logs.reporter -local ctxreport=logs.writer -function logs.setmessenger(m) - ctxreport=m -end -function logs.messenger(category,subcategory) - if subcategory then - return function(...) - ctxreport(subdirect(category,subcategory,...)) - end - else - return function(...) - ctxreport(direct(category,...)) - end - end -end -local function setblocked(category,value) - if category==true then - category,value="*",true - elseif category==false then - category,value="*",false - elseif value==nil then - value=true - end - if category=="*" then - states=value - for k,v in next,data do - v.state=value - end - else - states=utilities.parsers.settings_to_hash(category) - for c,_ in next,states do - if data[c] then - v.state=value - else - c=topattern(c,true,true) - for k,v in next,data do - if find(k,c) then - v.state=value - end - end - end - end - end -end -function logs.disable(category,value) - setblocked(category,value==nil and true or value) -end -function logs.enable(category) - setblocked(category,false) -end -function logs.categories() - return table.sortedkeys(data) -end -function logs.show() - local n,c,s,max=0,0,0,0 - for category,v in table.sortedpairs(data) do - n=n+1 - local state=v.state - local reporters=v.reporters - local nc=#category - if nc>c then - c=nc - end - for subcategory,_ in next,reporters do - local ns=#subcategory - if ns>c then - s=ns - end - local m=nc+ns - if m>max then - max=m - end - end - local subcategories=concat(table.sortedkeys(reporters),", ") - if state==true then - state="disabled" - elseif state==false then - state="enabled" - else - state="unknown" - end - report("logging","category %a, subcategories %a, state %a",category,subcategories,state) - end - report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max) -end -local delayed_reporters={} -setmetatableindex(delayed_reporters,function(t,k) - local v=logs.reporter(k.name) - t[k]=v - return v -end) -function utilities.setters.report(setter,...) - delayed_reporters[setter](...) -end -directives.register("logs.blocked",function(v) - setblocked(v,true) -end) -directives.register("logs.target",function(v) - settarget(v) -end) -local report_pages=logs.reporter("pages") -local real,user,sub -function logs.start_page_number() - real=texgetcount("realpageno") - user=texgetcount("userpageno") - sub=texgetcount("subpageno") -end -local timing=false -local starttime=nil -local lasttime=nil -trackers.register("pages.timing",function(v) - starttime=os.clock() - timing=true -end) -function logs.stop_page_number() - if timing then - local elapsed,average - local stoptime=os.clock() - if not lasttime or real<2 then - elapsed=stoptime - average=stoptime - starttime=stoptime - else - elapsed=stoptime-lasttime - average=(stoptime-starttime)/(real-1) - end - lasttime=stoptime - if real<=0 then - report_pages("flushing page, time %0.04f / %0.04f",elapsed,average) - elseif user<=0 then - report_pages("flushing realpage %s, time %0.04f / %0.04f",real,elapsed,average) - elseif sub<=0 then - report_pages("flushing realpage %s, userpage %s, time %0.04f / %0.04f",real,user,elapsed,average) - else - report_pages("flushing realpage %s, userpage %s, subpage %s, time %0.04f / %0.04f",real,user,sub,elapsed,average) - end - else - if real<=0 then - report_pages("flushing page") - elseif user<=0 then - report_pages("flushing realpage %s",real) - elseif sub<=0 then - report_pages("flushing realpage %s, userpage %s",real,user) - else - report_pages("flushing realpage %s, userpage %s, subpage %s",real,user,sub) - end - end - logs.flush() -end -local report_files=logs.reporter("files") -local nesting=0 -local verbose=false -local hasscheme=url.hasscheme -function logs.show_open(name) -end -function logs.show_close(name) -end -function logs.show_load(name) -end -local simple=logs.reporter("comment") -logs.simple=simple -logs.simpleline=simple -function logs.setprogram () end -function logs.extendbanner() end -function logs.reportlines () end -function logs.reportbanner() end -function logs.reportline () end -function logs.simplelines () end -function logs.help () end -local Carg,C,lpegmatch=lpeg.Carg,lpeg.C,lpeg.match -local p_newline=lpeg.patterns.newline -local linewise=( - Carg(1)*C((1-p_newline)^1)/function(t,s) t.report(s) end+Carg(1)*p_newline^2/function(t) t.report() end+p_newline -)^1 -local function reportlines(t,str) - if str then - lpegmatch(linewise,str,1,t) - end -end -local function reportbanner(t) - local banner=t.banner - if banner then - t.report(banner) - t.report() - end -end -local function reportversion(t) - local banner=t.banner - if banner then - t.report(banner) - end -end -local function reporthelp(t,...) - local helpinfo=t.helpinfo - if type(helpinfo)=="string" then - reportlines(t,helpinfo) - elseif type(helpinfo)=="table" then - for i=1,select("#",...) do - reportlines(t,t.helpinfo[select(i,...)]) - if i<n then - t.report() - end - end - end -end -local function reportinfo(t) - t.report() - reportlines(t,t.moreinfo) -end -local function reportexport(t,method) - report(t.helpinfo) -end -local reporters={ - lines=reportlines, - banner=reportbanner, - version=reportversion, - help=reporthelp, - info=reportinfo, - export=reportexport, -} -local exporters={ -} -logs.reporters=reporters -logs.exporters=exporters -function logs.application(t) - t.name=t.name or "unknown" - t.banner=t.banner - t.moreinfo=moreinfo - t.report=logs.reporter(t.name) - t.help=function(...) - reporters.banner(t) - reporters.help(t,...) - reporters.info(t) - end - t.export=function(...) - reporters.export(t,...) - end - t.identify=function() - reporters.banner(t) - end - t.version=function() - reporters.version(t) - end - return t -end -function logs.system(whereto,process,jobname,category,...) - local message=formatters["%s %s => %s => %s => %s\r"](os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...)) - for i=1,10 do - local f=io.open(whereto,"a") - if f then - f:write(message) - f:close() - break - else - sleep(0.1) - end - end -end -local report_system=logs.reporter("system","logs") -function logs.obsolete(old,new) - local o=loadstring("return "..new)() - if type(o)=="function" then - return function(...) - report_system("function %a is obsolete, use %a",old,new) - loadstring(old.."="..new.." return "..old)()(...) - end - elseif type(o)=="table" then - local t,m={},{} - m.__index=function(t,k) - report_system("table %a is obsolete, use %a",old,new) - m.__index,m.__newindex=o,o - return o[k] - end - m.__newindex=function(t,k,v) - report_system("table %a is obsolete, use %a",old,new) - m.__index,m.__newindex=o,o - o[k]=v - end - if libraries then - libraries.obsolete[old]=t - end - setmetatable(t,m) - return t - end -end -if utilities then - utilities.report=report_system -end -if tex and tex.error then - function logs.texerrormessage(...) - tex.error(format(...),{}) - end -else - function logs.texerrormessage(...) - print(format(...)) - end -end -io.stdout:setvbuf('no') -io.stderr:setvbuf('no') -if package.helpers.report then - package.helpers.report=logs.reporter("package loader") -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-inf"] = package.loaded["trac-inf"] or true - --- original size: 6643, stripped down to: 5272 - -if not modules then modules={} end modules ['trac-inf']={ - version=1.001, - comment="companion to trac-inf.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,tonumber,select=type,tonumber,select -local format,lower=string.format,string.lower -local concat=table.concat -local clock=os.gettimeofday or os.clock -local setmetatableindex=table.setmetatableindex -local serialize=table.serialize -local formatters=string.formatters -statistics=statistics or {} -local statistics=statistics -statistics.enable=true -statistics.threshold=0.01 -local statusinfo,n,registered,timers={},0,{},{} -setmetatableindex(timers,function(t,k) - local v={ timing=0,loadtime=0 } - t[k]=v - return v -end) -local function hastiming(instance) - return instance and timers[instance] -end -local function resettiming(instance) - timers[instance or "notimer"]={ timing=0,loadtime=0 } -end -local function starttiming(instance) - local timer=timers[instance or "notimer"] - local it=timer.timing or 0 - if it==0 then - timer.starttime=clock() - if not timer.loadtime then - timer.loadtime=0 - end - end - timer.timing=it+1 -end -local function stoptiming(instance) - local timer=timers[instance or "notimer"] - local it=timer.timing - if it>1 then - timer.timing=it-1 - else - local starttime=timer.starttime - if starttime then - local stoptime=clock() - local loadtime=stoptime-starttime - timer.stoptime=stoptime - timer.loadtime=timer.loadtime+loadtime - timer.timing=0 - return loadtime - end - end - return 0 -end -local function elapsed(instance) - if type(instance)=="number" then - return instance or 0 - else - local timer=timers[instance or "notimer"] - return timer and timer.loadtime or 0 - end -end -local function elapsedtime(instance) - return format("%0.3f",elapsed(instance)) -end -local function elapsedindeed(instance) - return elapsed(instance)>statistics.threshold -end -local function elapsedseconds(instance,rest) - if elapsedindeed(instance) then - return format("%0.3f seconds %s",elapsed(instance),rest or "") - end -end -statistics.hastiming=hastiming -statistics.resettiming=resettiming -statistics.starttiming=starttiming -statistics.stoptiming=stoptiming -statistics.elapsed=elapsed -statistics.elapsedtime=elapsedtime -statistics.elapsedindeed=elapsedindeed -statistics.elapsedseconds=elapsedseconds -function statistics.register(tag,fnc) - if statistics.enable and type(fnc)=="function" then - local rt=registered[tag] or (#statusinfo+1) - statusinfo[rt]={ tag,fnc } - registered[tag]=rt - if #tag>n then n=#tag end - end -end -local report=logs.reporter("mkiv lua stats") -function statistics.show() - if statistics.enable then - local register=statistics.register - register("used platform",function() - local mask=lua.mask or "ascii" - return format("%s, type: %s, binary subtree: %s, symbol mask: %s (%s)", - os.platform or "unknown",os.type or "unknown",environment.texos or "unknown", - mask,mask=="utf" and "τεχ" or "tex") - end) - register("luatex banner",function() - return lower(status.banner) - end) - register("control sequences",function() - return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra) - end) - register("callbacks",function() - local total,indirect=status.callbacks or 0,status.indirect_callbacks or 0 - return format("%s direct, %s indirect, %s total",total-indirect,indirect,total) - end) - if jit then - local status={ jit.status() } - if status[1] then - register("luajit status",function() - return concat(status," ",2) - end) - end - end - register("current memory usage",statistics.memused) - register("runtime",statistics.runtime) - logs.newline() - for i=1,#statusinfo do - local s=statusinfo[i] - local r=s[2]() - if r then - report("%s: %s",s[1],r) - end - end - statistics.enable=false - end -end -function statistics.memused() - local round=math.round or math.floor - return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000)) -end -starttiming(statistics) -function statistics.formatruntime(runtime) - return format("%s seconds",runtime) -end -function statistics.runtime() - stoptiming(statistics) - return statistics.formatruntime(elapsedtime(statistics)) -end -local report=logs.reporter("system") -function statistics.timed(action) - starttiming("run") - action() - stoptiming("run") - report("total runtime: %s seconds",elapsedtime("run")) -end -function statistics.tracefunction(base,tag,...) - for i=1,select("#",...) do - local name=select(i,...) - local stat={} - local func=base[name] - setmetatableindex(stat,function(t,k) t[k]=0 return 0 end) - base[name]=function(n,k,v) stat[k]=stat[k]+1 return func(n,k,v) end - statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end) - end -end -commands=commands or {} -function commands.resettimer(name) - resettiming(name or "whatever") - starttiming(name or "whatever") -end -function commands.elapsedtime(name) - stoptiming(name or "whatever") - context(elapsedtime(name or "whatever")) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-pro"] = package.loaded["trac-pro"] or true - --- original size: 5829, stripped down to: 3501 - -if not modules then modules={} end modules ['trac-pro']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local getmetatable,setmetatable,rawset,type=getmetatable,setmetatable,rawset,type -local trace_namespaces=false trackers.register("system.namespaces",function(v) trace_namespaces=v end) -local report_system=logs.reporter("system","protection") -namespaces=namespaces or {} -local namespaces=namespaces -local registered={} -local function report_index(k,name) - if trace_namespaces then - report_system("reference to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) - else - report_system("reference to %a in protected namespace %a",k,name) - end -end -local function report_newindex(k,name) - if trace_namespaces then - report_system("assignment to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) - else - report_system("assignment to %a in protected namespace %a",k,name) - end -end -local function register(name) - local data=name=="global" and _G or _G[name] - if not data then - return - end - registered[name]=data - local m=getmetatable(data) - if not m then - m={} - setmetatable(data,m) - end - local index,newindex={},{} - m.__saved__index=m.__index - m.__no__index=function(t,k) - if not index[k] then - index[k]=true - report_index(k,name) - end - return nil - end - m.__saved__newindex=m.__newindex - m.__no__newindex=function(t,k,v) - if not newindex[k] then - newindex[k]=true - report_newindex(k,name) - end - rawset(t,k,v) - end - m.__protection__depth=0 -end -local function private(name) - local data=registered[name] - if not data then - data=_G[name] - if not data then - data={} - _G[name]=data - end - register(name) - end - return data -end -local function protect(name) - local data=registered[name] - if not data then - return - end - local m=getmetatable(data) - local pd=m.__protection__depth - if pd>0 then - m.__protection__depth=pd+1 - else - m.__save_d_index,m.__saved__newindex=m.__index,m.__newindex - m.__index,m.__newindex=m.__no__index,m.__no__newindex - m.__protection__depth=1 - end -end -local function unprotect(name) - local data=registered[name] - if not data then - return - end - local m=getmetatable(data) - local pd=m.__protection__depth - if pd>1 then - m.__protection__depth=pd-1 - else - m.__index,m.__newindex=m.__saved__index,m.__saved__newindex - m.__protection__depth=0 - end -end -local function protectall() - for name,_ in next,registered do - if name~="global" then - protect(name) - end - end -end -local function unprotectall() - for name,_ in next,registered do - if name~="global" then - unprotect(name) - end - end -end -namespaces.register=register -namespaces.private=private -namespaces.protect=protect -namespaces.unprotect=unprotect -namespaces.protectall=protectall -namespaces.unprotectall=unprotectall -namespaces.private("namespaces") registered={} register("global") -directives.register("system.protect",function(v) - if v then - protectall() - else - unprotectall() - end -end) -directives.register("system.checkglobals",function(v) - if v then - report_system("enabling global namespace guard") - protect("global") - else - report_system("disabling global namespace guard") - unprotect("global") - end -end) - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-lua"] = package.loaded["util-lua"] or true - --- original size: 4982, stripped down to: 3511 - -if not modules then modules={} end modules ['util-lua']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - comment="the strip code is written by Peter Cawley", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local rep,sub,byte,dump,format=string.rep,string.sub,string.byte,string.dump,string.format -local load,loadfile,type=load,loadfile,type -utilities=utilities or {} -utilities.lua=utilities.lua or {} -local luautilities=utilities.lua -local report_lua=logs.reporter("system","lua") -local tracestripping=false -local forcestupidcompile=true -luautilities.stripcode=true -luautilities.alwaysstripcode=false -luautilities.nofstrippedchunks=0 -luautilities.nofstrippedbytes=0 -local strippedchunks={} -luautilities.strippedchunks=strippedchunks -luautilities.suffixes={ - tma="tma", - tmc=jit and "tmb" or "tmc", - lua="lua", - luc=jit and "lub" or "luc", - lui="lui", - luv="luv", - luj="luj", - tua="tua", - tuc="tuc", -} -local function register(name) - if tracestripping then - report_lua("stripped bytecode from %a",name or "unknown") - end - strippedchunks[#strippedchunks+1]=name - luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1 -end -local function stupidcompile(luafile,lucfile,strip) - local code=io.loaddata(luafile) - if code and code~="" then - code=load(code) - if code then - code=dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode) - if code and code~="" then - register(name) - io.savedata(lucfile,code) - return true,0 - end - else - report_lua("fatal error %a in file %a",1,luafile) - end - else - report_lua("fatal error %a in file %a",2,luafile) - end - return false,0 -end -function luautilities.loadedluacode(fullname,forcestrip,name) - name=name or fullname - local code,message - if environment.loadpreprocessedfile then - code,message=environment.loadpreprocessedfile(fullname) - else - code,message=loadfile(fullname) - end - if code then - code() - else - report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message") - end - if forcestrip and luautilities.stripcode then - if type(forcestrip)=="function" then - forcestrip=forcestrip(fullname) - end - if forcestrip or luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end - elseif luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end -end -function luautilities.strippedloadstring(code,forcestrip,name) - local code,message=load(code) - if not code then - report_lua("loading of file %a failed:\n\t%s",name,message or "no message") - end - if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end -end -function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) - report_lua("compiling %a into %a",luafile,lucfile) - os.remove(lucfile) - local done=stupidcompile(luafile,lucfile,strip~=false) - if done then - report_lua("dumping %a into %a stripped",luafile,lucfile) - if cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then - report_lua("removing %a",luafile) - os.remove(luafile) - end - end - return done -end -function luautilities.loadstripped(...) - local l=load(...) - if l then - return load(dump(l,true)) - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-deb"] = package.loaded["util-deb"] or true - --- original size: 3898, stripped down to: 2644 - -if not modules then modules={} end modules ['util-deb']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local debug=require "debug" -local getinfo=debug.getinfo -local type,next,tostring=type,next,tostring -local format,find=string.format,string.find -local is_boolean=string.is_boolean -utilities=utilities or {} -local debugger=utilities.debugger or {} -utilities.debugger=debugger -local counters={} -local names={} -local report=logs.reporter("debugger") -local function hook() - local f=getinfo(2) - if f then - local n="unknown" - if f.what=="C" then - n=f.name or '<anonymous>' - if not names[n] then - names[n]=format("%42s",n) - end - else - n=f.name or f.namewhat or f.what - if not n or n=="" then - n="?" - end - if not names[n] then - names[n]=format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source") - end - end - counters[n]=(counters[n] or 0)+1 - end -end -function debugger.showstats(printer,threshold) - printer=printer or report - threshold=threshold or 0 - local total,grandtotal,functions=0,0,0 - local dataset={} - for name,count in next,counters do - dataset[#dataset+1]={ name,count } - end - table.sort(dataset,function(a,b) return a[2]==b[2] and b[1]>a[1] or a[2]>b[2] end) - for i=1,#dataset do - local d=dataset[i] - local name=d[1] - local count=d[2] - if count>threshold and not find(name,"for generator") then - printer(format("%8i %s\n",count,names[name])) - total=total+count - end - grandtotal=grandtotal+count - functions=functions+1 - end - printer("\n") - printer(format("functions : % 10i\n",functions)) - printer(format("total : % 10i\n",total)) - printer(format("grand total: % 10i\n",grandtotal)) - printer(format("threshold : % 10i\n",threshold)) -end -function debugger.savestats(filename,threshold) - local f=io.open(filename,'w') - if f then - debugger.showstats(function(str) f:write(str) end,threshold) - f:close() - end -end -function debugger.enable() - debug.sethook(hook,"c") -end -function debugger.disable() - debug.sethook() -end -local function showtraceback(rep) - local level=2 - local reporter=rep or report - while true do - local info=getinfo(level,"Sl") - if not info then - break - elseif info.what=="C" then - reporter("%2i : %s",level-1,"C function") - else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) - end - level=level+1 - end -end -debugger.showtraceback=showtraceback - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-mrg"] = package.loaded["util-mrg"] or true - --- original size: 7757, stripped down to: 6015 - -if not modules then modules={} end modules ['util-mrg']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local gsub,format=string.gsub,string.format -local concat=table.concat -local type,next=type,next -local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt,Cb,Cg=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt,lpeg.Cb,lpeg.Cg -local lpegmatch,patterns=lpeg.match,lpeg.patterns -utilities=utilities or {} -local merger=utilities.merger or {} -utilities.merger=merger -merger.strip_comment=true -local report=logs.reporter("system","merge") -utilities.report=report -local m_begin_merge="begin library merge" -local m_end_merge="end library merge" -local m_begin_closure="do -- create closure to overcome 200 locals limit" -local m_end_closure="end -- of closure" -local m_pattern="%c+".."%-%-%s+"..m_begin_merge.."%c+(.-)%c+".."%-%-%s+"..m_end_merge.."%c+" -local m_format="\n\n-- "..m_begin_merge.."\n%s\n".."-- "..m_end_merge.."\n\n" -local m_faked="-- ".."created merged file".."\n\n".."-- "..m_begin_merge.."\n\n".."-- "..m_end_merge.."\n\n" -local m_report=[[ --- used libraries : %s --- skipped libraries : %s --- original bytes : %s --- stripped bytes : %s -]] -local m_preloaded=[[package.loaded[%q] = package.loaded[%q] or true]] -local function self_fake() - return m_faked -end -local function self_nothing() - return "" -end -local function self_load(name) - local data=io.loaddata(name) or "" - if data=="" then - report("unknown file %a",name) - else - report("inserting file %a",name) - end - return data or "" -end -local space=patterns.space -local eol=patterns.newline -local equals=P("=")^0 -local open=P("[")*Cg(equals,"init")*P("[")*P("\n")^-1 -local close=P("]")*C(equals)*P("]") -local closeeq=Cmt(close*Cb("init"),function(s,i,a,b) return a==b end) -local longstring=open*(1-closeeq)^0*close -local quoted=patterns.quoted -local digit=patterns.digit -local emptyline=space^0*eol -local operator1=P("<=")+P(">=")+P("~=")+P("..")+S("/^<>=*+%%") -local operator2=S("*+/") -local operator3=S("-") -local operator4=P("..") -local separator=S(",;") -local ignore=(P("]")*space^1*P("=")*space^1*P("]"))/"]=["+(P("=")*space^1*P("{"))/"={"+(P("(")*space^1)/"("+(P("{")*(space+eol)^1*P("}"))/"{}" -local strings=quoted -local longcmt=(emptyline^0*P("--")*longstring*emptyline^0)/"" -local longstr=longstring -local comment=emptyline^0*P("--")*P("-")^0*(1-eol)^0*emptyline^1/"\n" -local optionalspaces=space^0/"" -local mandatespaces=space^1/"" -local optionalspacing=(eol+space)^0/"" -local mandatespacing=(eol+space)^1/"" -local pack=digit*space^1*operator4*optionalspacing+optionalspacing*operator1*optionalspacing+optionalspacing*operator2*optionalspaces+mandatespacing*operator3*mandatespaces+optionalspaces*separator*optionalspaces -local lines=emptyline^2/"\n" -local spaces=(space*space)/" " -local compact=Cs (( - ignore+strings+longcmt+longstr+comment+pack+lines+spaces+1 -)^1 ) -local strip=Cs((emptyline^2/"\n"+1)^0) -local stripreturn=Cs((1-P("return")*space^1*P(1-space-eol)^1*(space+eol)^0*P(-1))^1) -function merger.compact(data) - return lpegmatch(strip,lpegmatch(compact,data)) -end -local function self_compact(data) - local delta=0 - if merger.strip_comment then - local before=#data - data=lpegmatch(compact,data) - data=lpegmatch(strip,data) - local after=#data - delta=before-after - report("original size %s, compacted to %s, stripped %s",before,after,delta) - data=format("-- original size: %s, stripped down to: %s\n\n%s",before,after,data) - end - return lpegmatch(stripreturn,data) or data,delta -end -local function self_save(name,data) - if data~="" then - io.savedata(name,data) - report("saving %s with size %s",name,#data) - end -end -local function self_swap(data,code) - return data~="" and (gsub(data,m_pattern,function() return format(m_format,code) end,1)) or "" -end -local function self_libs(libs,list) - local result,f,frozen,foundpath={},nil,false,nil - result[#result+1]="\n" - if type(libs)=='string' then libs={ libs } end - if type(list)=='string' then list={ list } end - for i=1,#libs do - local lib=libs[i] - for j=1,#list do - local pth=gsub(list[j],"\\","/") - report("checking library path %a",pth) - local name=pth.."/"..lib - if lfs.isfile(name) then - foundpath=pth - end - end - if foundpath then break end - end - if foundpath then - report("using library path %a",foundpath) - local right,wrong,original,stripped={},{},0,0 - for i=1,#libs do - local lib=libs[i] - local fullname=foundpath.."/"..lib - if lfs.isfile(fullname) then - report("using library %a",fullname) - local preloaded=file.nameonly(lib) - local data=io.loaddata(fullname,true) - original=original+#data - local data,delta=self_compact(data) - right[#right+1]=lib - result[#result+1]=m_begin_closure - result[#result+1]=format(m_preloaded,preloaded,preloaded) - result[#result+1]=data - result[#result+1]=m_end_closure - stripped=stripped+delta - else - report("skipping library %a",fullname) - wrong[#wrong+1]=lib - end - end - right=#right>0 and concat(right," ") or "-" - wrong=#wrong>0 and concat(wrong," ") or "-" - report("used libraries: %a",right) - report("skipped libraries: %a",wrong) - report("original bytes: %a",original) - report("stripped bytes: %a",stripped) - result[#result+1]=format(m_report,right,wrong,original,stripped) - else - report("no valid library path found") - end - return concat(result,"\n\n") -end -function merger.selfcreate(libs,list,target) - if target then - self_save(target,self_swap(self_fake(),self_libs(libs,list))) - end -end -function merger.selfmerge(name,libs,list,target) - self_save(target or name,self_swap(self_load(name),self_libs(libs,list))) -end -function merger.selfclean(name) - self_save(name,self_swap(self_load(name),self_nothing())) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-tpl"] = package.loaded["util-tpl"] or true - --- original size: 6251, stripped down to: 3488 - -if not modules then modules={} end modules ['util-tpl']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -utilities.templates=utilities.templates or {} -local templates=utilities.templates -local trace_template=false trackers.register("templates.trace",function(v) trace_template=v end) -local report_template=logs.reporter("template") -local tostring=tostring -local format,sub,byte=string.format,string.sub,string.byte -local P,C,R,Cs,Cc,Carg,lpegmatch,lpegpatterns=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.match,lpeg.patterns -local replacer -local function replacekey(k,t,how,recursive) - local v=t[k] - if not v then - if trace_template then - report_template("unknown key %a",k) - end - return "" - else - v=tostring(v) - if trace_template then - report_template("setting key %a to value %a",k,v) - end - if recursive then - return lpegmatch(replacer,v,1,t,how,recursive) - else - return v - end - end -end -local sqlescape=lpeg.replacer { - { "'","''" }, - { "\\","\\\\" }, - { "\r\n","\\n" }, - { "\r","\\n" }, -} -local sqlquoted=lpeg.Cs(lpeg.Cc("'")*sqlescape*lpeg.Cc("'")) -lpegpatterns.sqlescape=sqlescape -lpegpatterns.sqlquoted=sqlquoted -local luaescape=lpegpatterns.luaescape -local escapers={ - lua=function(s) - return lpegmatch(luaescape,s) - end, - sql=function(s) - return lpegmatch(sqlescape,s) - end, -} -local quotedescapers={ - lua=function(s) - return format("%q",s) - end, - sql=function(s) - return lpegmatch(sqlquoted,s) - end, -} -local luaescaper=escapers.lua -local quotedluaescaper=quotedescapers.lua -local function replacekeyunquoted(s,t,how,recurse) - local escaper=how and escapers[how] or luaescaper - return escaper(replacekey(s,t,how,recurse)) -end -local function replacekeyquoted(s,t,how,recurse) - local escaper=how and quotedescapers[how] or quotedluaescaper - return escaper(replacekey(s,t,how,recurse)) -end -local single=P("%") -local double=P("%%") -local lquoted=P("%[") -local rquoted=P("]%") -local lquotedq=P("%(") -local rquotedq=P(")%") -local escape=double/'%%' -local nosingle=single/'' -local nodouble=double/'' -local nolquoted=lquoted/'' -local norquoted=rquoted/'' -local nolquotedq=lquotedq/'' -local norquotedq=rquotedq/'' -local key=nosingle*((C((1-nosingle )^1)*Carg(1)*Carg(2)*Carg(3))/replacekey )*nosingle -local quoted=nolquotedq*((C((1-norquotedq)^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyquoted )*norquotedq -local unquoted=nolquoted*((C((1-norquoted )^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyunquoted)*norquoted -local any=P(1) - replacer=Cs((unquoted+quoted+escape+key+any)^0) -local function replace(str,mapping,how,recurse) - if mapping and str then - return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str - else - return str - end -end -templates.replace=replace -function templates.replacer(str,how,recurse) - return function(mapping) - return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str - end -end -function templates.load(filename,mapping,how,recurse) - local data=io.loaddata(filename) or "" - if mapping and next(mapping) then - return replace(data,mapping,how,recurse) - else - return data - end -end -function templates.resolve(t,mapping,how,recurse) - if not mapping then - mapping=t - end - for k,v in next,t do - t[k]=replace(v,mapping,how,recurse) - end - return t -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-env"] = package.loaded["util-env"] or true - --- original size: 8807, stripped down to: 5085 - -if not modules then modules={} end modules ['util-env']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local allocate,mark=utilities.storage.allocate,utilities.storage.mark -local format,sub,match,gsub,find=string.format,string.sub,string.match,string.gsub,string.find -local unquoted,quoted=string.unquoted,string.quoted -local concat,insert,remove=table.concat,table.insert,table.remove -environment=environment or {} -local environment=environment -os.setlocale(nil,nil) -function os.setlocale() -end -local validengines=allocate { - ["luatex"]=true, - ["luajittex"]=true, -} -local basicengines=allocate { - ["luatex"]="luatex", - ["texlua"]="luatex", - ["texluac"]="luatex", - ["luajittex"]="luajittex", - ["texluajit"]="luajittex", -} -local luaengines=allocate { - ["lua"]=true, - ["luajit"]=true, -} -environment.validengines=validengines -environment.basicengines=basicengines -if not arg then - environment.used_as_library=true -elseif luaengines[file.removesuffix(arg[-1])] then -elseif validengines[file.removesuffix(arg[0])] then - if arg[1]=="--luaonly" then - arg[-1]=arg[0] - arg[ 0]=arg[2] - for k=3,#arg do - arg[k-2]=arg[k] - end - remove(arg) - remove(arg) - else - end - local originalzero=file.basename(arg[0]) - local specialmapping={ luatools=="base" } - if originalzero~="mtxrun" and originalzero~="mtxrun.lua" then - arg[0]=specialmapping[originalzero] or originalzero - insert(arg,0,"--script") - insert(arg,0,"mtxrun") - end -end -environment.arguments=allocate() -environment.files=allocate() -environment.sortedflags=nil -function environment.initializearguments(arg) - local arguments,files={},{} - environment.arguments,environment.files,environment.sortedflags=arguments,files,nil - for index=1,#arg do - local argument=arg[index] - if index>0 then - local flag,value=match(argument,"^%-+(.-)=(.-)$") - if flag then - flag=gsub(flag,"^c:","") - arguments[flag]=unquoted(value or "") - else - flag=match(argument,"^%-+(.+)") - if flag then - flag=gsub(flag,"^c:","") - arguments[flag]=true - else - files[#files+1]=argument - end - end - end - end - environment.ownname=file.reslash(environment.ownname or arg[0] or 'unknown.lua') -end -function environment.setargument(name,value) - environment.arguments[name]=value -end -function environment.getargument(name,partial) - local arguments,sortedflags=environment.arguments,environment.sortedflags - if arguments[name] then - return arguments[name] - elseif partial then - if not sortedflags then - sortedflags=allocate(table.sortedkeys(arguments)) - for k=1,#sortedflags do - sortedflags[k]="^"..sortedflags[k] - end - environment.sortedflags=sortedflags - end - for k=1,#sortedflags do - local v=sortedflags[k] - if find(name,v) then - return arguments[sub(v,2,#v)] - end - end - end - return nil -end -environment.argument=environment.getargument -function environment.splitarguments(separator) - local done,before,after=false,{},{} - local originalarguments=environment.originalarguments - for k=1,#originalarguments do - local v=originalarguments[k] - if not done and v==separator then - done=true - elseif done then - after[#after+1]=v - else - before[#before+1]=v - end - end - return before,after -end -function environment.reconstructcommandline(arg,noquote) - arg=arg or environment.originalarguments - if noquote and #arg==1 then - local a=arg[1] - a=resolvers.resolve(a) - a=unquoted(a) - return a - elseif #arg>0 then - local result={} - for i=1,#arg do - local a=arg[i] - a=resolvers.resolve(a) - a=unquoted(a) - a=gsub(a,'"','\\"') - if find(a," ") then - result[#result+1]=quoted(a) - else - result[#result+1]=a - end - end - return concat(result," ") - else - return "" - end -end -function environment.relativepath(path,root) - if not path then - path="" - end - if not file.is_rootbased_path(path) then - if not root then - root=file.pathpart(environment.ownscript or environment.ownname or ".") - end - if root=="" then - root="." - end - path=root.."/"..path - end - return file.collapsepath(path,true) -end -if arg then - local newarg,instring={},false - for index=1,#arg do - local argument=arg[index] - if find(argument,"^\"") then - newarg[#newarg+1]=gsub(argument,"^\"","") - if not find(argument,"\"$") then - instring=true - end - elseif find(argument,"\"$") then - newarg[#newarg]=newarg[#newarg].." "..gsub(argument,"\"$","") - instring=false - elseif instring then - newarg[#newarg]=newarg[#newarg].." "..argument - else - newarg[#newarg+1]=argument - end - end - for i=1,-5,-1 do - newarg[i]=arg[i] - end - environment.initializearguments(newarg) - environment.originalarguments=mark(newarg) - environment.rawarguments=mark(arg) - arg={} -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["luat-env"] = package.loaded["luat-env"] or true - --- original size: 5930, stripped down to: 4235 - - if not modules then modules={} end modules ['luat-env']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local rawset,rawget,loadfile,assert=rawset,rawget,loadfile,assert -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local report_lua=logs.reporter("resolvers","lua") -local luautilities=utilities.lua -local luasuffixes=luautilities.suffixes -local texgettoks=tex and tex.gettoks -environment=environment or {} -local environment=environment -local mt={ - __index=function(_,k) - if k=="version" then - local version=texgettoks and texgettoks("contextversiontoks") - if version and version~="" then - rawset(environment,"version",version) - return version - else - return "unknown" - end - elseif k=="kind" then - local kind=texgettoks and texgettoks("contextkindtoks") - if kind and kind~="" then - rawset(environment,"kind",kind) - return kind - else - return "unknown" - end - elseif k=="jobname" or k=="formatname" then - local name=tex and tex[k] - if name or name=="" then - rawset(environment,k,name) - return name - else - return "unknown" - end - elseif k=="outputfilename" then - local name=environment.jobname - rawset(environment,k,name) - return name - end - end -} -setmetatable(environment,mt) -function environment.texfile(filename) - return resolvers.findfile(filename,'tex') -end -function environment.luafile(filename) - local resolved=resolvers.findfile(filename,'tex') or "" - if resolved~="" then - return resolved - end - resolved=resolvers.findfile(filename,'texmfscripts') or "" - if resolved~="" then - return resolved - end - return resolvers.findfile(filename,'luatexlibs') or "" -end -local stripindeed=false directives.register("system.compile.strip",function(v) stripindeed=v end) -local function strippable(filename) - if stripindeed then - local modu=modules[file.nameonly(filename)] - return modu and modu.dataonly - else - return false - end -end -function environment.luafilechunk(filename,silent) - filename=file.replacesuffix(filename,"lua") - local fullname=environment.luafile(filename) - if fullname and fullname~="" then - local data=luautilities.loadedluacode(fullname,strippable,filename) - if trace_locating then - report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded") - elseif not silent then - texio.write("<",data and "+ " or "- ",fullname,">") - end - return data - else - if trace_locating then - report_lua("unknown file %a",filename) - end - return nil - end -end -function environment.loadluafile(filename,version) - local lucname,luaname,chunk - local basename=file.removesuffix(filename) - if basename==filename then - luaname=file.addsuffix(basename,luasuffixes.lua) - lucname=file.addsuffix(basename,luasuffixes.luc) - else - luaname=basename - lucname=nil - end - local fullname=(lucname and environment.luafile(lucname)) or "" - if fullname~="" then - if trace_locating then - report_lua("loading %a",fullname) - end - chunk=loadfile(fullname) - end - if chunk then - assert(chunk)() - if version then - local v=version - if modules and modules[filename] then - v=modules[filename].version - elseif versions and versions[filename] then - v=versions[filename] - end - if v==version then - return true - else - if trace_locating then - report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version) - end - environment.loadluafile(filename) - end - else - return true - end - end - fullname=(luaname and environment.luafile(luaname)) or "" - if fullname~="" then - if trace_locating then - report_lua("loading %a",fullname) - end - chunk=loadfile(fullname) - if not chunk then - if trace_locating then - report_lua("unknown file %a",filename) - end - else - assert(chunk)() - return true - end - end - return false -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true - --- original size: 42614, stripped down to: 26694 - -if not modules then modules={} end modules ['lxml-tab']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local trace_entities=false trackers.register("xml.entities",function(v) trace_entities=v end) -local report_xml=logs and logs.reporter("xml","core") or function(...) print(string.format(...)) end -if lpeg.setmaxstack then lpeg.setmaxstack(1000) end -xml=xml or {} -local xml=xml -local concat,remove,insert=table.concat,table.remove,table.insert -local type,next,setmetatable,getmetatable,tonumber=type,next,setmetatable,getmetatable,tonumber -local lower,find,match,gsub=string.lower,string.find,string.match,string.gsub -local utfchar=utf.char -local lpegmatch=lpeg.match -local P,S,R,C,V,C,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.C,lpeg.Cs -local formatters=string.formatters -xml.xmlns=xml.xmlns or {} -local check=P(false) -local parse=check -function xml.registerns(namespace,pattern) - check=check+C(P(lower(pattern)))/namespace - parse=P { P(check)+1*V(1) } -end -function xml.checkns(namespace,url) - local ns=lpegmatch(parse,lower(url)) - if ns and namespace~=ns then - xml.xmlns[namespace]=ns - end -end -function xml.resolvens(url) - return lpegmatch(parse,lower(url)) or "" -end -local nsremap,resolvens=xml.xmlns,xml.resolvens -local stack={} -local top={} -local dt={} -local at={} -local xmlns={} -local errorstr=nil -local entities={} -local strip=false -local cleanup=false -local utfize=false -local resolve_predefined=false -local unify_predefined=false -local dcache={} -local hcache={} -local acache={} -local mt={} -local function initialize_mt(root) - mt={ __index=root } -end -function xml.setproperty(root,k,v) - getmetatable(root).__index[k]=v -end -function xml.checkerror(top,toclose) - return "" -end -local function add_attribute(namespace,tag,value) - if cleanup and #value>0 then - value=cleanup(value) - end - if tag=="xmlns" then - xmlns[#xmlns+1]=resolvens(value) - at[tag]=value - elseif namespace=="" then - at[tag]=value - elseif namespace=="xmlns" then - xml.checkns(tag,value) - at["xmlns:"..tag]=value - else - at[namespace..":"..tag]=value - end -end -local function add_empty(spacing,namespace,tag) - if #spacing>0 then - dt[#dt+1]=spacing - end - local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace - top=stack[#stack] - dt=top.dt - local t={ ns=namespace or "",rn=resolved,tg=tag,at=at,dt={},__p__=top } - dt[#dt+1]=t - setmetatable(t,mt) - if at.xmlns then - remove(xmlns) - end - at={} -end -local function add_begin(spacing,namespace,tag) - if #spacing>0 then - dt[#dt+1]=spacing - end - local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace - top={ ns=namespace or "",rn=resolved,tg=tag,at=at,dt={},__p__=stack[#stack] } - setmetatable(top,mt) - dt=top.dt - stack[#stack+1]=top - at={} -end -local function add_end(spacing,namespace,tag) - if #spacing>0 then - dt[#dt+1]=spacing - end - local toclose=remove(stack) - top=stack[#stack] - if #stack<1 then - errorstr=formatters["unable to close %s %s"](tag,xml.checkerror(top,toclose) or "") - elseif toclose.tg~=tag then - errorstr=formatters["unable to close %s with %s %s"](toclose.tg,tag,xml.checkerror(top,toclose) or "") - end - dt=top.dt - dt[#dt+1]=toclose - if toclose.at.xmlns then - remove(xmlns) - end -end -local function add_text(text) - if cleanup and #text>0 then - dt[#dt+1]=cleanup(text) - else - dt[#dt+1]=text - end -end -local function add_special(what,spacing,text) - if #spacing>0 then - dt[#dt+1]=spacing - end - if strip and (what=="@cm@" or what=="@dt@") then - else - dt[#dt+1]={ special=true,ns="",tg=what,dt={ text } } - end -end -local function set_message(txt) - errorstr="garbage at the end of the file: "..gsub(txt,"([ \n\r\t]*)","") -end -local reported_attribute_errors={} -local function attribute_value_error(str) - if not reported_attribute_errors[str] then - report_xml("invalid attribute value %a",str) - reported_attribute_errors[str]=true - at._error_=str - end - return str -end -local function attribute_specification_error(str) - if not reported_attribute_errors[str] then - report_xml("invalid attribute specification %a",str) - reported_attribute_errors[str]=true - at._error_=str - end - return str -end -xml.placeholders={ - unknown_dec_entity=function(str) return str=="" and "&error;" or formatters["&%s;"](str) end, - unknown_hex_entity=function(str) return formatters["&#x%s;"](str) end, - unknown_any_entity=function(str) return formatters["&#x%s;"](str) end, -} -local placeholders=xml.placeholders -local function fromhex(s) - local n=tonumber(s,16) - if n then - return utfchar(n) - else - return formatters["h:%s"](s),true - end -end -local function fromdec(s) - local n=tonumber(s) - if n then - return utfchar(n) - else - return formatters["d:%s"](s),true - end -end -local rest=(1-P(";"))^0 -local many=P(1)^0 -local parsedentity=P("&")*(P("#x")*(rest/fromhex)+P("#")*(rest/fromdec))*P(";")*P(-1)+(P("#x")*(many/fromhex)+P("#")*(many/fromdec)) -local predefined_unified={ - [38]="&", - [42]=""", - [47]="'", - [74]="<", - [76]=">", -} -local predefined_simplified={ - [38]="&",amp="&", - [42]='"',quot='"', - [47]="'",apos="'", - [74]="<",lt="<", - [76]=">",gt=">", -} -local nofprivates=0xF0000 -local privates_u={ - [ [[&]] ]="&", - [ [["]] ]=""", - [ [[']] ]="'", - [ [[<]] ]="<", - [ [[>]] ]=">", -} -local privates_p={} -local privates_n={ -} -local escaped=utf.remapper(privates_u) -local function unescaped(s) - local p=privates_n[s] - if not p then - nofprivates=nofprivates+1 - p=utfchar(nofprivates) - privates_n[s]=p - s="&"..s..";" - privates_u[p]=s - privates_p[p]=s - end - return p -end -local unprivatized=utf.remapper(privates_p) -xml.privatetoken=unescaped -xml.unprivatized=unprivatized -xml.privatecodes=privates_n -local function handle_hex_entity(str) - local h=hcache[str] - if not h then - local n=tonumber(str,16) - h=unify_predefined and predefined_unified[n] - if h then - if trace_entities then - report_xml("utfize, converting hex entity &#x%s; into %a",str,h) - end - elseif utfize then - h=(n and utfchar(n)) or xml.unknown_hex_entity(str) or "" - if not n then - report_xml("utfize, ignoring hex entity &#x%s;",str) - elseif trace_entities then - report_xml("utfize, converting hex entity &#x%s; into %a",str,h) - end - else - if trace_entities then - report_xml("found entity &#x%s;",str) - end - h="&#x"..str..";" - end - hcache[str]=h - end - return h -end -local function handle_dec_entity(str) - local d=dcache[str] - if not d then - local n=tonumber(str) - d=unify_predefined and predefined_unified[n] - if d then - if trace_entities then - report_xml("utfize, converting dec entity &#%s; into %a",str,d) - end - elseif utfize then - d=(n and utfchar(n)) or placeholders.unknown_dec_entity(str) or "" - if not n then - report_xml("utfize, ignoring dec entity &#%s;",str) - elseif trace_entities then - report_xml("utfize, converting dec entity &#%s; into %a",str,d) - end - else - if trace_entities then - report_xml("found entity &#%s;",str) - end - d="&#"..str..";" - end - dcache[str]=d - end - return d -end -xml.parsedentitylpeg=parsedentity -local function handle_any_entity(str) - if resolve then - local a=acache[str] - if not a then - a=resolve_predefined and predefined_simplified[str] - if a then - if trace_entities then - report_xml("resolving entity &%s; to predefined %a",str,a) - end - else - if type(resolve)=="function" then - a=resolve(str) or entities[str] - else - a=entities[str] - end - if a then - if type(a)=="function" then - if trace_entities then - report_xml("expanding entity &%s; to function call",str) - end - a=a(str) or "" - end - a=lpegmatch(parsedentity,a) or a - if trace_entities then - report_xml("resolving entity &%s; to internal %a",str,a) - end - else - local unknown_any_entity=placeholders.unknown_any_entity - if unknown_any_entity then - a=unknown_any_entity(str) or "" - end - if a then - if trace_entities then - report_xml("resolving entity &%s; to external %s",str,a) - end - else - if trace_entities then - report_xml("keeping entity &%s;",str) - end - if str=="" then - a="&error;" - else - a="&"..str..";" - end - end - end - end - acache[str]=a - elseif trace_entities then - if not acache[str] then - report_xml("converting entity &%s; to %a",str,a) - acache[str]=a - end - end - return a - else - local a=acache[str] - if not a then - a=resolve_predefined and predefined_simplified[str] - if a then - acache[str]=a - if trace_entities then - report_xml("entity &%s; becomes %a",str,a) - end - elseif str=="" then - if trace_entities then - report_xml("invalid entity &%s;",str) - end - a="&error;" - acache[str]=a - else - if trace_entities then - report_xml("entity &%s; is made private",str) - end - a=unescaped(str) - acache[str]=a - end - end - return a - end -end -local function handle_end_entity(chr) - report_xml("error in entity, %a found instead of %a",chr,";") -end -local space=S(' \r\n\t') -local open=P('<') -local close=P('>') -local squote=S("'") -local dquote=S('"') -local equal=P('=') -local slash=P('/') -local colon=P(':') -local semicolon=P(';') -local ampersand=P('&') -local valid=R('az','AZ','09')+S('_-.') -local name_yes=C(valid^1)*colon*C(valid^1) -local name_nop=C(P(true))*C(valid^1) -local name=name_yes+name_nop -local utfbom=lpeg.patterns.utfbom -local spacing=C(space^0) -local anyentitycontent=(1-open-semicolon-space-close)^0 -local hexentitycontent=R("AF","af","09")^0 -local decentitycontent=R("09")^0 -local parsedentity=P("#")/""*( - P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity) - )+(anyentitycontent/handle_any_entity) -local entity=ampersand/""*parsedentity*((semicolon/"")+#(P(1)/handle_end_entity)) -local text_unparsed=C((1-open)^1) -local text_parsed=Cs(((1-open-ampersand)^1+entity)^1) -local somespace=space^1 -local optionalspace=space^0 -local value=(squote*Cs((entity+(1-squote))^0)*squote)+(dquote*Cs((entity+(1-dquote))^0)*dquote) -local endofattributes=slash*close+close -local whatever=space*name*optionalspace*equal -local wrongvalue=Cs(P(entity+(1-space-endofattributes))^1)/attribute_value_error -local attributevalue=value+wrongvalue -local attribute=(somespace*name*optionalspace*equal*optionalspace*attributevalue)/add_attribute -local attributes=(attribute+somespace^-1*(((1-endofattributes)^1)/attribute_specification_error))^0 -local parsedtext=text_parsed/add_text -local unparsedtext=text_unparsed/add_text -local balanced=P { "["*((1-S"[]")+V(1))^0*"]" } -local emptyelement=(spacing*open*name*attributes*optionalspace*slash*close)/add_empty -local beginelement=(spacing*open*name*attributes*optionalspace*close)/add_begin -local endelement=(spacing*open*slash*name*optionalspace*close)/add_end -local begincomment=open*P("!--") -local endcomment=P("--")*close -local begininstruction=open*P("?") -local endinstruction=P("?")*close -local begincdata=open*P("![CDATA[") -local endcdata=P("]]")*close -local someinstruction=C((1-endinstruction)^0) -local somecomment=C((1-endcomment )^0) -local somecdata=C((1-endcdata )^0) -local function normalentity(k,v ) entities[k]=v end -local function systementity(k,v,n) entities[k]=v end -local function publicentity(k,v,n) entities[k]=v end -local begindoctype=open*P("!DOCTYPE") -local enddoctype=close -local beginset=P("[") -local endset=P("]") -local doctypename=C((1-somespace-close)^0) -local elementdoctype=optionalspace*P("<!ELEMENT")*(1-close)^0*close -local basiccomment=begincomment*((1-endcomment)^0)*endcomment -local normalentitytype=(doctypename*somespace*value)/normalentity -local publicentitytype=(doctypename*somespace*P("PUBLIC")*somespace*value)/publicentity -local systementitytype=(doctypename*somespace*P("SYSTEM")*somespace*value*somespace*P("NDATA")*somespace*doctypename)/systementity -local entitydoctype=optionalspace*P("<!ENTITY")*somespace*(systementitytype+publicentitytype+normalentitytype)*optionalspace*close -local doctypeset=beginset*optionalspace*P(elementdoctype+entitydoctype+basiccomment+space)^0*optionalspace*endset -local definitiondoctype=doctypename*somespace*doctypeset -local publicdoctype=doctypename*somespace*P("PUBLIC")*somespace*value*somespace*value*somespace*doctypeset -local systemdoctype=doctypename*somespace*P("SYSTEM")*somespace*value*somespace*doctypeset -local simpledoctype=(1-close)^1 -local somedoctype=C((somespace*(publicdoctype+systemdoctype+definitiondoctype+simpledoctype)*optionalspace)^0) -local instruction=(spacing*begininstruction*someinstruction*endinstruction)/function(...) add_special("@pi@",...) end -local comment=(spacing*begincomment*somecomment*endcomment )/function(...) add_special("@cm@",...) end -local cdata=(spacing*begincdata*somecdata*endcdata )/function(...) add_special("@cd@",...) end -local doctype=(spacing*begindoctype*somedoctype*enddoctype )/function(...) add_special("@dt@",...) end -local trailer=space^0*(text_unparsed/set_message)^0 -local grammar_parsed_text=P { "preamble", - preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0*V("parent")*trailer, - parent=beginelement*V("children")^0*endelement, - children=parsedtext+V("parent")+emptyelement+comment+cdata+instruction, -} -local grammar_unparsed_text=P { "preamble", - preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0*V("parent")*trailer, - parent=beginelement*V("children")^0*endelement, - children=unparsedtext+V("parent")+emptyelement+comment+cdata+instruction, -} -local function _xmlconvert_(data,settings) - settings=settings or {} - strip=settings.strip_cm_and_dt - utfize=settings.utfize_entities - resolve=settings.resolve_entities - resolve_predefined=settings.resolve_predefined_entities - unify_predefined=settings.unify_predefined_entities - cleanup=settings.text_cleanup - entities=settings.entities or {} - if utfize==nil then - settings.utfize_entities=true - utfize=true - end - if resolve_predefined==nil then - settings.resolve_predefined_entities=true - resolve_predefined=true - end - stack,top,at,xmlns,errorstr={},{},{},{},nil - acache,hcache,dcache={},{},{} - reported_attribute_errors={} - if settings.parent_root then - mt=getmetatable(settings.parent_root) - else - initialize_mt(top) - end - stack[#stack+1]=top - top.dt={} - dt=top.dt - if not data or data=="" then - errorstr="empty xml file" - elseif utfize or resolve then - if lpegmatch(grammar_parsed_text,data) then - errorstr="" - else - errorstr="invalid xml file - parsed text" - end - elseif type(data)=="string" then - if lpegmatch(grammar_unparsed_text,data) then - errorstr="" - else - errorstr="invalid xml file - unparsed text" - end - else - errorstr="invalid xml file - no text at all" - end - local result - if errorstr and errorstr~="" then - result={ dt={ { ns="",tg="error",dt={ errorstr },at={},er=true } } } - setmetatable(stack,mt) - local errorhandler=settings.error_handler - if errorhandler==false then - else - errorhandler=errorhandler or xml.errorhandler - if errorhandler then - local currentresource=settings.currentresource - if currentresource and currentresource~="" then - xml.errorhandler(formatters["load error in [%s]: %s"](currentresource,errorstr)) - else - xml.errorhandler(formatters["load error: %s"](errorstr)) - end - end - end - else - result=stack[1] - end - if not settings.no_root then - result={ special=true,ns="",tg='@rt@',dt=result.dt,at={},entities=entities,settings=settings } - setmetatable(result,mt) - local rdt=result.dt - for k=1,#rdt do - local v=rdt[k] - if type(v)=="table" and not v.special then - result.ri=k - v.__p__=result - break - end - end - end - if errorstr and errorstr~="" then - result.error=true - else - errorstr=nil - end - result.statistics={ - errormessage=errorstr, - entities={ - decimals=dcache, - hexadecimals=hcache, - names=acache, - } - } - strip,utfize,resolve,resolve_predefined=nil,nil,nil,nil - unify_predefined,cleanup,entities=nil,nil,nil - stack,top,at,xmlns,errorstr=nil,nil,nil,nil,nil - acache,hcache,dcache=nil,nil,nil - reported_attribute_errors,mt,errorhandler=nil,nil,nil - return result -end -function xmlconvert(data,settings) - local ok,result=pcall(function() return _xmlconvert_(data,settings) end) - if ok then - return result - else - return _xmlconvert_("",settings) - end -end -xml.convert=xmlconvert -function xml.inheritedconvert(data,xmldata) - local settings=xmldata.settings - if settings then - settings.parent_root=xmldata - end - local xc=xmlconvert(data,settings) - return xc -end -function xml.is_valid(root) - return root and root.dt and root.dt[1] and type(root.dt[1])=="table" and not root.dt[1].er -end -function xml.package(tag,attributes,data) - local ns,tg=match(tag,"^(.-):?([^:]+)$") - local t={ ns=ns,tg=tg,dt=data or "",at=attributes or {} } - setmetatable(t,mt) - return t -end -function xml.is_valid(root) - return root and not root.error -end -xml.errorhandler=report_xml -function xml.load(filename,settings) - local data="" - if type(filename)=="string" then - local f=io.open(filename,'r') - if f then - data=f:read("*all") - f:close() - end - elseif filename then - data=filename:read("*all") - end - if settings then - settings.currentresource=filename - local result=xmlconvert(data,settings) - settings.currentresource=nil - return result - else - return xmlconvert(data,{ currentresource=filename }) - end -end -local no_root={ no_root=true } -function xml.toxml(data) - if type(data)=="string" then - local root={ xmlconvert(data,no_root) } - return (#root>1 and root) or root[1] - else - return data - end -end -local function copy(old,tables) - if old then - tables=tables or {} - local new={} - if not tables[old] then - tables[old]=new - end - for k,v in next,old do - new[k]=(type(v)=="table" and (tables[v] or copy(v,tables))) or v - end - local mt=getmetatable(old) - if mt then - setmetatable(new,mt) - end - return new - else - return {} - end -end -xml.copy=copy -function xml.checkbom(root) - if root.ri then - local dt=root.dt - for k=1,#dt do - local v=dt[k] - if type(v)=="table" and v.special and v.tg=="@pi@" and find(v.dt[1],"xml.*version=") then - return - end - end - insert(dt,1,{ special=true,ns="",tg="@pi@",dt={ "xml version='1.0' standalone='yes'" } } ) - insert(dt,2,"\n" ) - end -end -local function verbose_element(e,handlers) - local handle=handlers.handle - local serialize=handlers.serialize - local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn - local ats=eat and next(eat) and {} - if ats then - for k,v in next,eat do - ats[#ats+1]=formatters['%s=%q'](k,escaped(v)) - end - end - if ern and trace_entities and ern~=ens then - ens=ern - end - if ens~="" then - if edt and #edt>0 then - if ats then - handle("<",ens,":",etg," ",concat(ats," "),">") - else - handle("<",ens,":",etg,">") - end - for i=1,#edt do - local e=edt[i] - if type(e)=="string" then - handle(escaped(e)) - else - serialize(e,handlers) - end - end - handle("</",ens,":",etg,">") - else - if ats then - handle("<",ens,":",etg," ",concat(ats," "),"/>") - else - handle("<",ens,":",etg,"/>") - end - end - else - if edt and #edt>0 then - if ats then - handle("<",etg," ",concat(ats," "),">") - else - handle("<",etg,">") - end - for i=1,#edt do - local e=edt[i] - if type(e)=="string" then - handle(escaped(e)) - else - serialize(e,handlers) - end - end - handle("</",etg,">") - else - if ats then - handle("<",etg," ",concat(ats," "),"/>") - else - handle("<",etg,"/>") - end - end - end -end -local function verbose_pi(e,handlers) - handlers.handle("<?",e.dt[1],"?>") -end -local function verbose_comment(e,handlers) - handlers.handle("<!--",e.dt[1],"-->") -end -local function verbose_cdata(e,handlers) - handlers.handle("<![CDATA[",e.dt[1],"]]>") -end -local function verbose_doctype(e,handlers) - handlers.handle("<!DOCTYPE ",e.dt[1],">") -end -local function verbose_root(e,handlers) - handlers.serialize(e.dt,handlers) -end -local function verbose_text(e,handlers) - handlers.handle(escaped(e)) -end -local function verbose_document(e,handlers) - local serialize=handlers.serialize - local functions=handlers.functions - for i=1,#e do - local ei=e[i] - if type(ei)=="string" then - functions["@tx@"](ei,handlers) - else - serialize(ei,handlers) - end - end -end -local function serialize(e,handlers,...) - if e then - local initialize=handlers.initialize - local finalize=handlers.finalize - local functions=handlers.functions - if initialize then - local state=initialize(...) - if not state==true then - return state - end - end - local etg=e.tg - if etg then - (functions[etg] or functions["@el@"])(e,handlers) - else - functions["@dc@"](e,handlers) - end - if finalize then - return finalize() - end - end -end -local function xserialize(e,handlers) - local functions=handlers.functions - local etg=e.tg - if etg then - (functions[etg] or functions["@el@"])(e,handlers) - else - functions["@dc@"](e,handlers) - end -end -local handlers={} -local function newhandlers(settings) - local t=table.copy(handlers[settings and settings.parent or "verbose"] or {}) - if settings then - for k,v in next,settings do - if type(v)=="table" then - local tk=t[k] if not tk then tk={} t[k]=tk end - for kk,vv in next,v do - tk[kk]=vv - end - else - t[k]=v - end - end - if settings.name then - handlers[settings.name]=t - end - end - utilities.storage.mark(t) - return t -end -local nofunction=function() end -function xml.sethandlersfunction(handler,name,fnc) - handler.functions[name]=fnc or nofunction -end -function xml.gethandlersfunction(handler,name) - return handler.functions[name] -end -function xml.gethandlers(name) - return handlers[name] -end -newhandlers { - name="verbose", - initialize=false, - finalize=false, - serialize=xserialize, - handle=print, - functions={ - ["@dc@"]=verbose_document, - ["@dt@"]=verbose_doctype, - ["@rt@"]=verbose_root, - ["@el@"]=verbose_element, - ["@pi@"]=verbose_pi, - ["@cm@"]=verbose_comment, - ["@cd@"]=verbose_cdata, - ["@tx@"]=verbose_text, - } -} -local result -local xmlfilehandler=newhandlers { - name="file", - initialize=function(name) - result=io.open(name,"wb") - return result - end, - finalize=function() - result:close() - return true - end, - handle=function(...) - result:write(...) - end, -} -function xml.save(root,name) - serialize(root,xmlfilehandler,name) -end -local result -local xmlstringhandler=newhandlers { - name="string", - initialize=function() - result={} - return result - end, - finalize=function() - return concat(result) - end, - handle=function(...) - result[#result+1]=concat {... } - end, -} -local function xmltostring(root) - if not root then - return "" - elseif type(root)=="string" then - return root - else - return serialize(root,xmlstringhandler) or "" - end -end -local function __tostring(root) - return (root and xmltostring(root)) or "" -end -initialize_mt=function(root) - mt={ __tostring=__tostring,__index=root } -end -xml.defaulthandlers=handlers -xml.newhandlers=newhandlers -xml.serialize=serialize -xml.tostring=xmltostring -local function xmlstring(e,handle) - if not handle or (e.special and e.tg~="@rt@") then - elseif e.tg then - local edt=e.dt - if edt then - for i=1,#edt do - xmlstring(edt[i],handle) - end - end - else - handle(e) - end -end -xml.string=xmlstring -function xml.settings(e) - while e do - local s=e.settings - if s then - return s - else - e=e.__p__ - end - end - return nil -end -function xml.root(e) - local r=e - while e do - e=e.__p__ - if e then - r=e - end - end - return r -end -function xml.parent(root) - return root.__p__ -end -function xml.body(root) - return root.ri and root.dt[root.ri] or root -end -function xml.name(root) - if not root then - return "" - end - local ns=root.ns - local tg=root.tg - if ns=="" then - return tg - else - return ns..":"..tg - end -end -function xml.erase(dt,k) - if dt then - if k then - dt[k]="" - else for k=1,#dt do - dt[1]={ "" } - end end - end -end -function xml.assign(dt,k,root) - if dt and k then - dt[k]=type(root)=="table" and xml.body(root) or root - return dt[k] - else - return xml.body(root) - end -end -function xml.tocdata(e,wrapper) - local whatever=type(e)=="table" and xmltostring(e.dt) or e or "" - if wrapper then - whatever=formatters["<%s>%s</%s>"](wrapper,whatever,wrapper) - end - local t={ special=true,ns="",tg="@cd@",at={},rn="",dt={ whatever },__p__=e } - setmetatable(t,getmetatable(e)) - e.dt={ t } -end -function xml.makestandalone(root) - if root.ri then - local dt=root.dt - for k=1,#dt do - local v=dt[k] - if type(v)=="table" and v.special and v.tg=="@pi@" then - local txt=v.dt[1] - if find(txt,"xml.*version=") then - v.dt[1]=txt.." standalone='yes'" - break - end - end - end - end - return root -end -function xml.kind(e) - local dt=e and e.dt - if dt then - local n=#dt - if n==1 then - local d=dt[1] - if d.special then - local tg=d.tg - if tg=="@cd@" then - return "cdata" - elseif tg=="@cm" then - return "comment" - elseif tg=="@pi@" then - return "instruction" - elseif tg=="@dt@" then - return "declaration" - end - elseif type(d)=="string" then - return "text" - end - return "element" - elseif n>0 then - return "mixed" - end - end - return "empty" -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true - --- original size: 48956, stripped down to: 30516 - -if not modules then modules={} end modules ['lxml-lpt']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local concat,remove,insert=table.concat,table.remove,table.insert -local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,tostring,setmetatable,load,select -local format,upper,lower,gmatch,gsub,find,rep=string.format,string.upper,string.lower,string.gmatch,string.gsub,string.find,string.rep -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local trace_lpath=false if trackers then trackers.register("xml.path",function(v) trace_lpath=v end) end -local trace_lparse=false if trackers then trackers.register("xml.parse",function(v) trace_lparse=v end) end -local trace_lprofile=false if trackers then trackers.register("xml.profile",function(v) trace_lpath=v trace_lparse=v trace_lprofile=v end) end -local report_lpath=logs.reporter("xml","lpath") -local xml=xml -local lpathcalls=0 function xml.lpathcalls () return lpathcalls end -local lpathcached=0 function xml.lpathcached() return lpathcached end -xml.functions=xml.functions or {} -local functions=xml.functions -xml.expressions=xml.expressions or {} -local expressions=xml.expressions -xml.finalizers=xml.finalizers or {} -local finalizers=xml.finalizers -xml.specialhandler=xml.specialhandler or {} -local specialhandler=xml.specialhandler -lpegpatterns.xml=lpegpatterns.xml or {} -local xmlpatterns=lpegpatterns.xml -finalizers.xml=finalizers.xml or {} -finalizers.tex=finalizers.tex or {} -local function fallback (t,name) - local fn=finalizers[name] - if fn then - t[name]=fn - else - report_lpath("unknown sub finalizer %a",name) - fn=function() end - end - return fn -end -setmetatableindex(finalizers.xml,fallback) -setmetatableindex(finalizers.tex,fallback) -xml.defaultprotocol="xml" -local apply_axis={} -apply_axis['root']=function(list) - local collected={} - for l=1,#list do - local ll=list[l] - local rt=ll - while ll do - ll=ll.__p__ - if ll then - rt=ll - end - end - collected[l]=rt - end - return collected -end -apply_axis['self']=function(list) - return list -end -apply_axis['child']=function(list) - local collected,c={},0 - for l=1,#list do - local ll=list[l] - local dt=ll.dt - if dt then - local en=0 - for k=1,#dt do - local dk=dt[k] - if dk.tg then - c=c+1 - collected[c]=dk - dk.ni=k - en=en+1 - dk.ei=en - end - end - ll.en=en - end - end - return collected -end -local function collect(list,collected,c) - local dt=list.dt - if dt then - local en=0 - for k=1,#dt do - local dk=dt[k] - if dk.tg then - c=c+1 - collected[c]=dk - dk.ni=k - en=en+1 - dk.ei=en - c=collect(dk,collected,c) - end - end - list.en=en - end - return c -end -apply_axis['descendant']=function(list) - local collected,c={},0 - for l=1,#list do - c=collect(list[l],collected,c) - end - return collected -end -local function collect(list,collected,c) - local dt=list.dt - if dt then - local en=0 - for k=1,#dt do - local dk=dt[k] - if dk.tg then - c=c+1 - collected[c]=dk - dk.ni=k - en=en+1 - dk.ei=en - c=collect(dk,collected,c) - end - end - list.en=en - end - return c -end -apply_axis['descendant-or-self']=function(list) - local collected,c={},0 - for l=1,#list do - local ll=list[l] - if ll.special~=true then - c=c+1 - collected[c]=ll - end - c=collect(ll,collected,c) - end - return collected -end -apply_axis['ancestor']=function(list) - local collected,c={},0 - for l=1,#list do - local ll=list[l] - while ll do - ll=ll.__p__ - if ll then - c=c+1 - collected[c]=ll - end - end - end - return collected -end -apply_axis['ancestor-or-self']=function(list) - local collected,c={},0 - for l=1,#list do - local ll=list[l] - c=c+1 - collected[c]=ll - while ll do - ll=ll.__p__ - if ll then - c=c+1 - collected[c]=ll - end - end - end - return collected -end -apply_axis['parent']=function(list) - local collected,c={},0 - for l=1,#list do - local pl=list[l].__p__ - if pl then - c=c+1 - collected[c]=pl - end - end - return collected -end -apply_axis['attribute']=function(list) - return {} -end -apply_axis['namespace']=function(list) - return {} -end -apply_axis['following']=function(list) - return {} -end -apply_axis['preceding']=function(list) - return {} -end -apply_axis['following-sibling']=function(list) - local collected,c={},0 - for l=1,#list do - local ll=list[l] - local p=ll.__p__ - local d=p.dt - for i=ll.ni+1,#d do - local di=d[i] - if type(di)=="table" then - c=c+1 - collected[c]=di - end - end - end - return collected -end -apply_axis['preceding-sibling']=function(list) - local collected,c={},0 - for l=1,#list do - local ll=list[l] - local p=ll.__p__ - local d=p.dt - for i=1,ll.ni-1 do - local di=d[i] - if type(di)=="table" then - c=c+1 - collected[c]=di - end - end - end - return collected -end -apply_axis['reverse-sibling']=function(list) - local collected,c={},0 - for l=1,#list do - local ll=list[l] - local p=ll.__p__ - local d=p.dt - for i=ll.ni-1,1,-1 do - local di=d[i] - if type(di)=="table" then - c=c+1 - collected[c]=di - end - end - end - return collected -end -apply_axis['auto-descendant-or-self']=apply_axis['descendant-or-self'] -apply_axis['auto-descendant']=apply_axis['descendant'] -apply_axis['auto-child']=apply_axis['child'] -apply_axis['auto-self']=apply_axis['self'] -apply_axis['initial-child']=apply_axis['child'] -local function apply_nodes(list,directive,nodes) - local maxn=#nodes - if maxn==3 then - local nns,ntg=nodes[2],nodes[3] - if not nns and not ntg then - if directive then - return list - else - return {} - end - else - local collected,c,m,p={},0,0,nil - if not nns then - for l=1,#list do - local ll=list[l] - local ltg=ll.tg - if ltg then - if directive then - if ntg==ltg then - local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end - c=c+1 - collected[c],ll.mi=ll,m - end - elseif ntg~=ltg then - local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end - c=c+1 - collected[c],ll.mi=ll,m - end - end - end - elseif not ntg then - for l=1,#list do - local ll=list[l] - local lns=ll.rn or ll.ns - if lns then - if directive then - if lns==nns then - local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end - c=c+1 - collected[c],ll.mi=ll,m - end - elseif lns~=nns then - local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end - c=c+1 - collected[c],ll.mi=ll,m - end - end - end - else - for l=1,#list do - local ll=list[l] - local ltg=ll.tg - if ltg then - local lns=ll.rn or ll.ns - local ok=ltg==ntg and lns==nns - if directive then - if ok then - local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end - c=c+1 - collected[c],ll.mi=ll,m - end - elseif not ok then - local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end - c=c+1 - collected[c],ll.mi=ll,m - end - end - end - end - return collected - end - else - local collected,c,m,p={},0,0,nil - for l=1,#list do - local ll=list[l] - local ltg=ll.tg - if ltg then - local lns=ll.rn or ll.ns - local ok=false - for n=1,maxn,3 do - local nns,ntg=nodes[n+1],nodes[n+2] - ok=(not ntg or ltg==ntg) and (not nns or lns==nns) - if ok then - break - end - end - if directive then - if ok then - local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end - c=c+1 - collected[c],ll.mi=ll,m - end - elseif not ok then - local llp=ll.__p__;if llp~=p then p,m=llp,1 else m=m+1 end - c=c+1 - collected[c],ll.mi=ll,m - end - end - end - return collected - end -end -local quit_expression=false -local function apply_expression(list,expression,order) - local collected,c={},0 - quit_expression=false - for l=1,#list do - local ll=list[l] - if expression(list,ll,l,order) then - c=c+1 - collected[c]=ll - end - if quit_expression then - break - end - end - return collected -end -local P,V,C,Cs,Cc,Ct,R,S,Cg,Cb=lpeg.P,lpeg.V,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.R,lpeg.S,lpeg.Cg,lpeg.Cb -local spaces=S(" \n\r\t\f")^0 -local lp_space=S(" \n\r\t\f") -local lp_any=P(1) -local lp_noequal=P("!=")/"~="+P("<=")+P(">=")+P("==") -local lp_doequal=P("=")/"==" -local lp_or=P("|")/" or " -local lp_and=P("&")/" and " -local lp_builtin=P ( - P("text")/"(ll.dt[1] or '')"+ - P("content")/"ll.dt"+ - P("name")/"((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)"+P("tag")/"ll.tg"+P("position")/"l"+ - P("firstindex")/"1"+P("lastindex")/"(#ll.__p__.dt or 1)"+P("firstelement")/"1"+P("lastelement")/"(ll.__p__.en or 1)"+P("first")/"1"+P("last")/"#list"+P("rootposition")/"order"+P("order")/"order"+P("element")/"(ll.ei or 1)"+P("index")/"(ll.ni or 1)"+P("match")/"(ll.mi or 1)"+ - P("ns")/"ll.ns" - )*((spaces*P("(")*spaces*P(")"))/"") -local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])") -lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0" -lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))" -local lp_fastpos=lp_fastpos_n+lp_fastpos_p -local lp_reserved=C("and")+C("or")+C("not")+C("div")+C("mod")+C("true")+C("false") -local lp_lua_function=Cs((R("az","AZ","__")^1*(P(".")*R("az","AZ","__")^1)^1)*("("))/"%0" -local lp_function=C(R("az","AZ","__")^1)*P("(")/function(t) - if expressions[t] then - return "expr."..t.."(" - else - return "expr.error(" - end -end -local lparent=P("(") -local rparent=P(")") -local noparent=1-(lparent+rparent) -local nested=P{lparent*(noparent+V(1))^0*rparent} -local value=P(lparent*C((noparent+nested)^0)*rparent) -local lp_child=Cc("expr.child(ll,'")*R("az","AZ","--","__")^1*Cc("')") -local lp_number=S("+-")*R("09")^1 -local lp_string=Cc("'")*R("az","AZ","--","__")^1*Cc("'") -local lp_content=(P("'")*(1-P("'"))^0*P("'")+P('"')*(1-P('"'))^0*P('"')) -local cleaner -local lp_special=(C(P("name")+P("text")+P("tag")+P("count")+P("child")))*value/function(t,s) - if expressions[t] then - s=s and s~="" and lpegmatch(cleaner,s) - if s and s~="" then - return "expr."..t.."(ll,"..s..")" - else - return "expr."..t.."(ll)" - end - else - return "expr.error("..t..")" - end -end -local content=lp_builtin+lp_attribute+lp_special+lp_noequal+lp_doequal+lp_or+lp_and+lp_reserved+lp_lua_function+lp_function+lp_content+ - lp_child+lp_any -local converter=Cs ( - lp_fastpos+(P { lparent*(V(1))^0*rparent+content } )^0 -) -cleaner=Cs (( - lp_reserved+lp_number+lp_string+1 )^1 ) -local template_e=[[ - local expr = xml.expressions - return function(list,ll,l,order) - return %s - end -]] -local template_f_y=[[ - local finalizer = xml.finalizers['%s']['%s'] - return function(collection) - return finalizer(collection,%s) - end -]] -local template_f_n=[[ - return xml.finalizers['%s']['%s'] -]] -local register_self={ kind="axis",axis="self" } -local register_parent={ kind="axis",axis="parent" } -local register_descendant={ kind="axis",axis="descendant" } -local register_child={ kind="axis",axis="child" } -local register_descendant_or_self={ kind="axis",axis="descendant-or-self" } -local register_root={ kind="axis",axis="root" } -local register_ancestor={ kind="axis",axis="ancestor" } -local register_ancestor_or_self={ kind="axis",axis="ancestor-or-self" } -local register_attribute={ kind="axis",axis="attribute" } -local register_namespace={ kind="axis",axis="namespace" } -local register_following={ kind="axis",axis="following" } -local register_following_sibling={ kind="axis",axis="following-sibling" } -local register_preceding={ kind="axis",axis="preceding" } -local register_preceding_sibling={ kind="axis",axis="preceding-sibling" } -local register_reverse_sibling={ kind="axis",axis="reverse-sibling" } -local register_auto_descendant_or_self={ kind="axis",axis="auto-descendant-or-self" } -local register_auto_descendant={ kind="axis",axis="auto-descendant" } -local register_auto_self={ kind="axis",axis="auto-self" } -local register_auto_child={ kind="axis",axis="auto-child" } -local register_initial_child={ kind="axis",axis="initial-child" } -local register_all_nodes={ kind="nodes",nodetest=true,nodes={ true,false,false } } -local skip={} -local function errorrunner_e(str,cnv) - if not skip[str] then - report_lpath("error in expression: %s => %s",str,cnv) - skip[str]=cnv or str - end - return false -end -local function errorrunner_f(str,arg) - report_lpath("error in finalizer: %s(%s)",str,arg or "") - return false -end -local function register_nodes(nodetest,nodes) - return { kind="nodes",nodetest=nodetest,nodes=nodes } -end -local function register_expression(expression) - local converted=lpegmatch(converter,expression) - local runner=load(format(template_e,converted)) - runner=(runner and runner()) or function() errorrunner_e(expression,converted) end - return { kind="expression",expression=expression,converted=converted,evaluator=runner } -end -local function register_finalizer(protocol,name,arguments) - local runner - if arguments and arguments~="" then - runner=load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments)) - else - runner=load(format(template_f_n,protocol or xml.defaultprotocol,name)) - end - runner=(runner and runner()) or function() errorrunner_f(name,arguments) end - return { kind="finalizer",name=name,arguments=arguments,finalizer=runner } -end -local expression=P { "ex", - ex="["*C((V("sq")+V("dq")+(1-S("[]"))+V("ex"))^0)*"]", - sq="'"*(1-S("'"))^0*"'", - dq='"'*(1-S('"'))^0*'"', -} -local arguments=P { "ar", - ar="("*Cs((V("sq")+V("dq")+V("nq")+P(1-P(")")))^0)*")", - nq=((1-S("),'\""))^1)/function(s) return format("%q",s) end, - sq=P("'")*(1-P("'"))^0*P("'"), - dq=P('"')*(1-P('"'))^0*P('"'), -} -local function register_error(str) - return { kind="error",error=format("unparsed: %s",str) } -end -local special_1=P("*")*Cc(register_auto_descendant)*Cc(register_all_nodes) -local special_2=P("/")*Cc(register_auto_self) -local special_3=P("")*Cc(register_auto_self) -local no_nextcolon=P(-1)+#(1-P(":")) -local no_nextlparent=P(-1)+#(1-P("(")) -local pathparser=Ct { "patterns", - patterns=spaces*V("protocol")*spaces*( - (V("special")*spaces*P(-1) )+(V("initial")*spaces*V("step")*spaces*(P("/")*spaces*V("step")*spaces)^0 ) - ), - protocol=Cg(V("letters"),"protocol")*P("://")+Cg(Cc(nil),"protocol"), - step=((V("shortcuts")+P("/")+V("axis"))*spaces*V("nodes")^0+V("error"))*spaces*V("expressions")^0*spaces*V("finalizer")^0, - axis=V("descendant")+V("child")+V("parent")+V("self")+V("root")+V("ancestor")+V("descendant_or_self")+V("following_sibling")+V("following")+V("reverse_sibling")+V("preceding_sibling")+V("preceding")+V("ancestor_or_self")+#(1-P(-1))*Cc(register_auto_child), - special=special_1+special_2+special_3, - initial=(P("/")*spaces*Cc(register_initial_child))^-1, - error=(P(1)^1)/register_error, - shortcuts_a=V("s_descendant_or_self")+V("s_descendant")+V("s_child")+V("s_parent")+V("s_self")+V("s_root")+V("s_ancestor"), - shortcuts=V("shortcuts_a")*(spaces*"/"*spaces*V("shortcuts_a"))^0, - s_descendant_or_self=(P("***/")+P("/"))*Cc(register_descendant_or_self), - s_descendant=P("**")*Cc(register_descendant), - s_child=P("*")*no_nextcolon*Cc(register_child ), - s_parent=P("..")*Cc(register_parent ), - s_self=P("." )*Cc(register_self ), - s_root=P("^^")*Cc(register_root ), - s_ancestor=P("^")*Cc(register_ancestor ), - descendant=P("descendant::")*Cc(register_descendant ), - child=P("child::")*Cc(register_child ), - parent=P("parent::")*Cc(register_parent ), - self=P("self::")*Cc(register_self ), - root=P('root::')*Cc(register_root ), - ancestor=P('ancestor::')*Cc(register_ancestor ), - descendant_or_self=P('descendant-or-self::')*Cc(register_descendant_or_self ), - ancestor_or_self=P('ancestor-or-self::')*Cc(register_ancestor_or_self ), - following=P('following::')*Cc(register_following ), - following_sibling=P('following-sibling::')*Cc(register_following_sibling ), - preceding=P('preceding::')*Cc(register_preceding ), - preceding_sibling=P('preceding-sibling::')*Cc(register_preceding_sibling ), - reverse_sibling=P('reverse-sibling::')*Cc(register_reverse_sibling ), - nodes=(V("nodefunction")*spaces*P("(")*V("nodeset")*P(")")+V("nodetest")*V("nodeset"))/register_nodes, - expressions=expression/register_expression, - letters=R("az")^1, - name=(1-S("/[]()|:*!"))^1, - negate=P("!")*Cc(false), - nodefunction=V("negate")+P("not")*Cc(false)+Cc(true), - nodetest=V("negate")+Cc(true), - nodename=(V("negate")+Cc(true))*spaces*((V("wildnodename")*P(":")*V("wildnodename"))+(Cc(false)*V("wildnodename"))), - wildnodename=(C(V("name"))+P("*")*Cc(false))*no_nextlparent, - nodeset=spaces*Ct(V("nodename")*(spaces*P("|")*spaces*V("nodename"))^0)*spaces, - finalizer=(Cb("protocol")*P("/")^-1*C(V("name"))*arguments*P(-1))/register_finalizer, -} -xmlpatterns.pathparser=pathparser -local cache={} -local function nodesettostring(set,nodetest) - local t={} - for i=1,#set,3 do - local directive,ns,tg=set[i],set[i+1],set[i+2] - if not ns or ns=="" then ns="*" end - if not tg or tg=="" then tg="*" end - tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg) - t[i]=(directive and tg) or format("not(%s)",tg) - end - if nodetest==false then - return format("not(%s)",concat(t,"|")) - else - return concat(t,"|") - end -end -local function tagstostring(list) - if #list==0 then - return "no elements" - else - local t={} - for i=1,#list do - local li=list[i] - local ns,tg=li.ns,li.tg - if not ns or ns=="" then ns="*" end - if not tg or tg=="" then tg="*" end - t[i]=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg) - end - return concat(t," ") - end -end -xml.nodesettostring=nodesettostring -local lpath -local lshowoptions={ functions=false } -local function lshow(parsed) - if type(parsed)=="string" then - parsed=lpath(parsed) - end - report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern, - table.serialize(parsed,false,lshowoptions)) -end -xml.lshow=lshow -local function add_comment(p,str) - local pc=p.comment - if not pc then - p.comment={ str } - else - pc[#pc+1]=str - end -end -lpath=function (pattern) - lpathcalls=lpathcalls+1 - if type(pattern)=="table" then - return pattern - else - local parsed=cache[pattern] - if parsed then - lpathcached=lpathcached+1 - else - parsed=lpegmatch(pathparser,pattern) - if parsed then - parsed.pattern=pattern - local np=#parsed - if np==0 then - parsed={ pattern=pattern,register_self,state="parsing error" } - report_lpath("parsing error in pattern: %s",pattern) - lshow(parsed) - else - local pi=parsed[1] - if pi.axis=="auto-child" then - if false then - add_comment(parsed,"auto-child replaced by auto-descendant-or-self") - parsed[1]=register_auto_descendant_or_self - else - add_comment(parsed,"auto-child replaced by auto-descendant") - parsed[1]=register_auto_descendant - end - elseif pi.axis=="initial-child" and np>1 and parsed[2].axis then - add_comment(parsed,"initial-child removed") - remove(parsed,1) - end - local np=#parsed - if np>1 then - local pnp=parsed[np] - if pnp.kind=="nodes" and pnp.nodetest==true then - local nodes=pnp.nodes - if nodes[1]==true and nodes[2]==false and nodes[3]==false then - add_comment(parsed,"redundant final wildcard filter removed") - remove(parsed,np) - end - end - end - end - else - parsed={ pattern=pattern } - end - cache[pattern]=parsed - if trace_lparse and not trace_lprofile then - lshow(parsed) - end - end - return parsed - end -end -xml.lpath=lpath -local profiled={} xml.profiled=profiled -local function profiled_apply(list,parsed,nofparsed,order) - local p=profiled[parsed.pattern] - if p then - p.tested=p.tested+1 - else - p={ tested=1,matched=0,finalized=0 } - profiled[parsed.pattern]=p - end - local collected=list - for i=1,nofparsed do - local pi=parsed[i] - local kind=pi.kind - if kind=="axis" then - collected=apply_axis[pi.axis](collected) - elseif kind=="nodes" then - collected=apply_nodes(collected,pi.nodetest,pi.nodes) - elseif kind=="expression" then - collected=apply_expression(collected,pi.evaluator,order) - elseif kind=="finalizer" then - collected=pi.finalizer(collected) - p.matched=p.matched+1 - p.finalized=p.finalized+1 - return collected - end - if not collected or #collected==0 then - local pn=i<nofparsed and parsed[nofparsed] - if pn and pn.kind=="finalizer" then - collected=pn.finalizer(collected) - p.finalized=p.finalized+1 - return collected - end - return nil - end - end - if collected then - p.matched=p.matched+1 - end - return collected -end -local function traced_apply(list,parsed,nofparsed,order) - if trace_lparse then - lshow(parsed) - end - report_lpath("collecting: %s",parsed.pattern) - report_lpath("root tags : %s",tagstostring(list)) - report_lpath("order : %s",order or "unset") - local collected=list - for i=1,nofparsed do - local pi=parsed[i] - local kind=pi.kind - if kind=="axis" then - collected=apply_axis[pi.axis](collected) - report_lpath("% 10i : ax : %s",(collected and #collected) or 0,pi.axis) - elseif kind=="nodes" then - collected=apply_nodes(collected,pi.nodetest,pi.nodes) - report_lpath("% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest)) - elseif kind=="expression" then - collected=apply_expression(collected,pi.evaluator,order) - report_lpath("% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted) - elseif kind=="finalizer" then - collected=pi.finalizer(collected) - report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "") - return collected - end - if not collected or #collected==0 then - local pn=i<nofparsed and parsed[nofparsed] - if pn and pn.kind=="finalizer" then - collected=pn.finalizer(collected) - report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "") - return collected - end - return nil - end - end - return collected -end -local function normal_apply(list,parsed,nofparsed,order) - local collected=list - for i=1,nofparsed do - local pi=parsed[i] - local kind=pi.kind - if kind=="axis" then - local axis=pi.axis - if axis~="self" then - collected=apply_axis[axis](collected) - end - elseif kind=="nodes" then - collected=apply_nodes(collected,pi.nodetest,pi.nodes) - elseif kind=="expression" then - collected=apply_expression(collected,pi.evaluator,order) - elseif kind=="finalizer" then - return pi.finalizer(collected) - end - if not collected or #collected==0 then - local pf=i<nofparsed and parsed[nofparsed].finalizer - if pf then - return pf(collected) - end - return nil - end - end - return collected -end -local function applylpath(list,pattern) - if not list then - return - end - local parsed=cache[pattern] - if parsed then - lpathcalls=lpathcalls+1 - lpathcached=lpathcached+1 - elseif type(pattern)=="table" then - lpathcalls=lpathcalls+1 - parsed=pattern - else - parsed=lpath(pattern) or pattern - end - if not parsed then - return - end - local nofparsed=#parsed - if nofparsed==0 then - return - end - if not trace_lpath then - return normal_apply ({ list },parsed,nofparsed,list.mi) - elseif trace_lprofile then - return profiled_apply({ list },parsed,nofparsed,list.mi) - else - return traced_apply ({ list },parsed,nofparsed,list.mi) - end -end -xml.applylpath=applylpath -function xml.filter(root,pattern) - return applylpath(root,pattern) -end -expressions.child=function(e,pattern) - return applylpath(e,pattern) -end -expressions.count=function(e,pattern) - local collected=applylpath(e,pattern) - return pattern and (collected and #collected) or 0 -end -expressions.oneof=function(s,...) - for i=1,select("#",...) do - if s==select(i,...) then - return true - end - end - return false -end -expressions.error=function(str) - xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?"))) - return false -end -expressions.undefined=function(s) - return s==nil -end -expressions.quit=function(s) - if s or s==nil then - quit_expression=true - end - return true -end -expressions.print=function(...) - print(...) - return true -end -expressions.contains=find -expressions.find=find -expressions.upper=upper -expressions.lower=lower -expressions.number=tonumber -expressions.boolean=toboolean -function expressions.contains(str,pattern) - local t=type(str) - if t=="string" then - if find(str,pattern) then - return true - end - elseif t=="table" then - for i=1,#str do - local d=str[i] - if type(d)=="string" and find(d,pattern) then - return true - end - end - end - return false -end -local function traverse(root,pattern,handle) - local collected=applylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local r=e.__p__ - handle(r,r.dt,e.ni) - end - end -end -local function selection(root,pattern,handle) - local collected=applylpath(root,pattern) - if collected then - if handle then - for c=1,#collected do - handle(collected[c]) - end - else - return collected - end - end -end -xml.traverse=traverse -xml.selection=selection -local function dofunction(collected,fnc,...) - if collected then - local f=functions[fnc] - if f then - for c=1,#collected do - f(collected[c],...) - end - else - report_lpath("unknown function %a",fnc) - end - end -end -finalizers.xml["function"]=dofunction -finalizers.tex["function"]=dofunction -expressions.text=function(e,n) - local rdt=e.__p__.dt - return rdt and rdt[n] or "" -end -expressions.name=function(e,n) - local found=false - n=tonumber(n) or 0 - if n==0 then - found=type(e)=="table" and e - elseif n<0 then - local d,k=e.__p__.dt,e.ni - for i=k-1,1,-1 do - local di=d[i] - if type(di)=="table" then - if n==-1 then - found=di - break - else - n=n+1 - end - end - end - else - local d,k=e.__p__.dt,e.ni - for i=k+1,#d,1 do - local di=d[i] - if type(di)=="table" then - if n==1 then - found=di - break - else - n=n-1 - end - end - end - end - if found then - local ns,tg=found.rn or found.ns or "",found.tg - if ns~="" then - return ns..":"..tg - else - return tg - end - else - return "" - end -end -expressions.tag=function(e,n) - if not e then - return "" - else - local found=false - n=tonumber(n) or 0 - if n==0 then - found=(type(e)=="table") and e - elseif n<0 then - local d,k=e.__p__.dt,e.ni - for i=k-1,1,-1 do - local di=d[i] - if type(di)=="table" then - if n==-1 then - found=di - break - else - n=n+1 - end - end - end - else - local d,k=e.__p__.dt,e.ni - for i=k+1,#d,1 do - local di=d[i] - if type(di)=="table" then - if n==1 then - found=di - break - else - n=n-1 - end - end - end - end - return (found and found.tg) or "" - end -end -local dummy=function() end -function xml.elements(root,pattern,reverse) - local collected=applylpath(root,pattern) - if not collected then - return dummy - elseif reverse then - local c=#collected+1 - return function() - if c>1 then - c=c-1 - local e=collected[c] - local r=e.__p__ - return r,r.dt,e.ni - end - end - else - local n,c=#collected,0 - return function() - if c<n then - c=c+1 - local e=collected[c] - local r=e.__p__ - return r,r.dt,e.ni - end - end - end -end -function xml.collected(root,pattern,reverse) - local collected=applylpath(root,pattern) - if not collected then - return dummy - elseif reverse then - local c=#collected+1 - return function() - if c>1 then - c=c-1 - return collected[c] - end - end - else - local n,c=#collected,0 - return function() - if c<n then - c=c+1 - return collected[c] - end - end - end -end -function xml.inspect(collection,pattern) - pattern=pattern or "." - for e in xml.collected(collection,pattern or ".") do - report_lpath("pattern: %s\n\n%s\n",pattern,xml.tostring(e)) - end -end -local function split(e) - local dt=e.dt - if dt then - for i=1,#dt do - local dti=dt[i] - if type(dti)=="string" then - dti=gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1") - dti=gsub(dti,"[\n\r]+","\n\n") - dt[i]=dti - else - split(dti) - end - end - end - return e -end -function xml.finalizers.paragraphs(c) - for i=1,#c do - split(c[i]) - end - return c -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-mis"] = package.loaded["lxml-mis"] or true - --- original size: 3684, stripped down to: 1957 - -if not modules then modules={} end modules ['lxml-mis']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local xml,lpeg,string=xml,lpeg,string -local concat=table.concat -local type,next,tonumber,tostring,setmetatable,loadstring=type,next,tonumber,tostring,setmetatable,loadstring -local format,gsub,match=string.format,string.gsub,string.match -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local P,S,R,C,V,Cc,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.Cc,lpeg.Cs -lpegpatterns.xml=lpegpatterns.xml or {} -local xmlpatterns=lpegpatterns.xml -local function xmlgsub(t,old,new) - local dt=t.dt - if dt then - for k=1,#dt do - local v=dt[k] - if type(v)=="string" then - dt[k]=gsub(v,old,new) - else - xmlgsub(v,old,new) - end - end - end -end -function xml.stripleadingspaces(dk,d,k) - if d and k then - local dkm=d[k-1] - if dkm and type(dkm)=="string" then - local s=match(dkm,"\n(%s+)") - xmlgsub(dk,"\n"..rep(" ",#s),"\n") - end - end -end -local normal=(1-S("<&>"))^0 -local special=P("<")/"<"+P(">")/">"+P("&")/"&" -local escaped=Cs(normal*(special*normal)^0) -local normal=(1-S"&")^0 -local special=P("<")/"<"+P(">")/">"+P("&")/"&" -local unescaped=Cs(normal*(special*normal)^0) -local cleansed=Cs(((P("<")*(1-P(">"))^0*P(">"))/""+1)^0) -xmlpatterns.escaped=escaped -xmlpatterns.unescaped=unescaped -xmlpatterns.cleansed=cleansed -function xml.escaped (str) return lpegmatch(escaped,str) end -function xml.unescaped(str) return lpegmatch(unescaped,str) end -function xml.cleansed (str) return lpegmatch(cleansed,str) end -function xml.fillin(root,pattern,str,check) - local e=xml.first(root,pattern) - if e then - local n=#e.dt - if not check or n==0 or (n==1 and e.dt[1]=="") then - e.dt={ str } - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true - --- original size: 23804, stripped down to: 16817 - -if not modules then modules={} end modules ['lxml-aux']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local trace_manipulations=false trackers.register("lxml.manipulations",function(v) trace_manipulations=v end) -local report_xml=logs.reporter("xml") -local xml=xml -local xmlconvert,xmlcopy,xmlname=xml.convert,xml.copy,xml.name -local xmlinheritedconvert=xml.inheritedconvert -local xmlapplylpath=xml.applylpath -local xmlfilter=xml.filter -local type,setmetatable,getmetatable=type,setmetatable,getmetatable -local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat -local gmatch,gsub,format,find,strip=string.gmatch,string.gsub,string.format,string.find,string.strip -local utfbyte=utf.byte -local function report(what,pattern,c,e) - report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern) -end -local function withelements(e,handle,depth) - if e and handle then - local edt=e.dt - if edt then - depth=depth or 0 - for i=1,#edt do - local e=edt[i] - if type(e)=="table" then - handle(e,depth) - withelements(e,handle,depth+1) - end - end - end - end -end -xml.withelements=withelements -function xml.withelement(e,n,handle) - if e and n~=0 and handle then - local edt=e.dt - if edt then - if n>0 then - for i=1,#edt do - local ei=edt[i] - if type(ei)=="table" then - if n==1 then - handle(ei) - return - else - n=n-1 - end - end - end - elseif n<0 then - for i=#edt,1,-1 do - local ei=edt[i] - if type(ei)=="table" then - if n==-1 then - handle(ei) - return - else - n=n+1 - end - end - end - end - end - end -end -function xml.each(root,pattern,handle,reverse) - local collected=xmlapplylpath(root,pattern) - if collected then - if reverse then - for c=#collected,1,-1 do - handle(collected[c]) - end - else - for c=1,#collected do - handle(collected[c]) - end - end - return collected - end -end -function xml.processattributes(root,pattern,handle) - local collected=xmlapplylpath(root,pattern) - if collected and handle then - for c=1,#collected do - handle(collected[c].at) - end - end - return collected -end -function xml.collect(root,pattern) - return xmlapplylpath(root,pattern) -end -function xml.collecttexts(root,pattern,flatten) - local collected=xmlapplylpath(root,pattern) - if collected and flatten then - local xmltostring=xml.tostring - for c=1,#collected do - collected[c]=xmltostring(collected[c].dt) - end - end - return collected or {} -end -function xml.collect_tags(root,pattern,nonamespace) - local collected=xmlapplylpath(root,pattern) - if collected then - local t,n={},0 - for c=1,#collected do - local e=collected[c] - local ns,tg=e.ns,e.tg - n=n+1 - if nonamespace then - t[n]=tg - elseif ns=="" then - t[n]=tg - else - t[n]=ns..":"..tg - end - end - return t - end -end -local no_root={ no_root=true } -local function redo_ni(d) - for k=1,#d do - local dk=d[k] - if type(dk)=="table" then - dk.ni=k - end - end -end -local function xmltoelement(whatever,root) - if not whatever then - return nil - end - local element - if type(whatever)=="string" then - element=xmlinheritedconvert(whatever,root) - else - element=whatever - end - if element.error then - return whatever - end - if element then - end - return element -end -xml.toelement=xmltoelement -local function copiedelement(element,newparent) - if type(element)=="string" then - return element - else - element=xmlcopy(element).dt - if newparent and type(element)=="table" then - element.__p__=newparent - end - return element - end -end -function xml.delete(root,pattern) - if not pattern or pattern=="" then - local p=root.__p__ - if p then - if trace_manipulations then - report('deleting',"--",c,root) - end - local d=p.dt - remove(d,root.ni) - redo_ni(d) - end - else - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local p=e.__p__ - if p then - if trace_manipulations then - report('deleting',pattern,c,e) - end - local d=p.dt - remove(d,e.ni) - redo_ni(d) - end - end - end - end -end -function xml.replace(root,pattern,whatever) - local element=root and xmltoelement(whatever,root) - local collected=element and xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local p=e.__p__ - if p then - if trace_manipulations then - report('replacing',pattern,c,e) - end - local d=p.dt - d[e.ni]=copiedelement(element,p) - redo_ni(d) - end - end - end -end -local function wrap(e,wrapper) - local t={ - rn=e.rn, - tg=e.tg, - ns=e.ns, - at=e.at, - dt=e.dt, - __p__=e, - } - setmetatable(t,getmetatable(e)) - e.rn=wrapper.rn or e.rn or "" - e.tg=wrapper.tg or e.tg or "" - e.ns=wrapper.ns or e.ns or "" - e.at=fastcopy(wrapper.at) - e.dt={ t } -end -function xml.wrap(root,pattern,whatever) - if whatever then - local wrapper=xmltoelement(whatever,root) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - if trace_manipulations then - report('wrapping',pattern,c,e) - end - wrap(e,wrapper) - end - end - else - wrap(root,xmltoelement(pattern)) - end -end -local function inject_element(root,pattern,whatever,prepend) - local element=root and xmltoelement(whatever,root) - local collected=element and xmlapplylpath(root,pattern) - local function inject_e(e) - local r=e.__p__ - local d,k,rri=r.dt,e.ni,r.ri - local edt=(rri and d[rri].dt) or (d and d[k] and d[k].dt) - if edt then - local be,af - local cp=copiedelement(element,e) - if prepend then - be,af=cp,edt - else - be,af=edt,cp - end - local bn=#be - for i=1,#af do - bn=bn+1 - be[bn]=af[i] - end - if rri then - r.dt[rri].dt=be - else - d[k].dt=be - end - redo_ni(d) - end - end - if not collected then - elseif collected.tg then - inject_e(collected) - else - for c=1,#collected do - inject_e(collected[c]) - end - end -end -local function insert_element(root,pattern,whatever,before) - local element=root and xmltoelement(whatever,root) - local collected=element and xmlapplylpath(root,pattern) - local function insert_e(e) - local r=e.__p__ - local d,k=r.dt,e.ni - if not before then - k=k+1 - end - insert(d,k,copiedelement(element,r)) - redo_ni(d) - end - if not collected then - elseif collected.tg then - insert_e(collected) - else - for c=1,#collected do - insert_e(collected[c]) - end - end -end -xml.insert_element=insert_element -xml.insertafter=insert_element -xml.insertbefore=function(r,p,e) insert_element(r,p,e,true) end -xml.injectafter=inject_element -xml.injectbefore=function(r,p,e) inject_element(r,p,e,true) end -local function include(xmldata,pattern,attribute,recursive,loaddata) - pattern=pattern or 'include' - loaddata=loaddata or io.loaddata - local collected=xmlapplylpath(xmldata,pattern) - if collected then - for c=1,#collected do - local ek=collected[c] - local name=nil - local ekdt=ek.dt - local ekat=ek.at - local epdt=ek.__p__.dt - if not attribute or attribute=="" then - name=(type(ekdt)=="table" and ekdt[1]) or ekdt - end - if not name then - for a in gmatch(attribute or "href","([^|]+)") do - name=ekat[a] - if name then break end - end - end - local data=(name and name~="" and loaddata(name)) or "" - if data=="" then - epdt[ek.ni]="" - elseif ekat["parse"]=="text" then - epdt[ek.ni]=xml.escaped(data) - else - local xi=xmlinheritedconvert(data,xmldata) - if not xi then - epdt[ek.ni]="" - else - if recursive then - include(xi,pattern,attribute,recursive,loaddata) - end - epdt[ek.ni]=xml.body(xi) - end - end - end - end -end -xml.include=include -local function stripelement(e,nolines,anywhere) - local edt=e.dt - if edt then - if anywhere then - local t,n={},0 - for e=1,#edt do - local str=edt[e] - if type(str)~="string" then - n=n+1 - t[n]=str - elseif str~="" then - if nolines then - str=gsub(str,"%s+"," ") - end - str=gsub(str,"^%s*(.-)%s*$","%1") - if str~="" then - n=n+1 - t[n]=str - end - end - end - e.dt=t - else - if #edt>0 then - local str=edt[1] - if type(str)~="string" then - elseif str=="" then - remove(edt,1) - else - if nolines then - str=gsub(str,"%s+"," ") - end - str=gsub(str,"^%s+","") - if str=="" then - remove(edt,1) - else - edt[1]=str - end - end - end - local nedt=#edt - if nedt>0 then - local str=edt[nedt] - if type(str)~="string" then - elseif str=="" then - remove(edt) - else - if nolines then - str=gsub(str,"%s+"," ") - end - str=gsub(str,"%s+$","") - if str=="" then - remove(edt) - else - edt[nedt]=str - end - end - end - end - end - return e -end -xml.stripelement=stripelement -function xml.strip(root,pattern,nolines,anywhere) - local collected=xmlapplylpath(root,pattern) - if collected then - for i=1,#collected do - stripelement(collected[i],nolines,anywhere) - end - end -end -local function renamespace(root,oldspace,newspace) - local ndt=#root.dt - for i=1,ndt or 0 do - local e=root[i] - if type(e)=="table" then - if e.ns==oldspace then - e.ns=newspace - if e.rn then - e.rn=newspace - end - end - local edt=e.dt - if edt then - renamespace(edt,oldspace,newspace) - end - end - end -end -xml.renamespace=renamespace -function xml.remaptag(root,pattern,newtg) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - collected[c].tg=newtg - end - end -end -function xml.remapnamespace(root,pattern,newns) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - collected[c].ns=newns - end - end -end -function xml.checknamespace(root,pattern,newns) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - if (not e.rn or e.rn=="") and e.ns=="" then - e.rn=newns - end - end - end -end -function xml.remapname(root,pattern,newtg,newns,newrn) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - e.tg,e.ns,e.rn=newtg,newns,newrn - end - end -end -function xml.cdatatotext(e) - local dt=e.dt - if #dt==1 then - local first=dt[1] - if first.tg=="@cd@" then - e.dt=first.dt - end - else - end -end -function xml.texttocdata(e) - local dt=e.dt - local s=xml.tostring(dt) - e.tg="@cd@" - e.special=true - e.ns="" - e.rn="" - e.dt={ s } - e.at=nil -end -function xml.elementtocdata(e) - local dt=e.dt - local s=xml.tostring(e) - e.tg="@cd@" - e.special=true - e.ns="" - e.rn="" - e.dt={ s } - e.at=nil -end -xml.builtinentities=table.tohash { "amp","quot","apos","lt","gt" } -local entities=characters and characters.entities or nil -local builtinentities=xml.builtinentities -function xml.addentitiesdoctype(root,option) - if not entities then - require("char-ent") - entities=characters.entities - end - if entities and root and root.tg=="@rt@" and root.statistics then - local list={} - local hexify=option=="hexadecimal" - for k,v in table.sortedhash(root.statistics.entities.names) do - if not builtinentities[k] then - local e=entities[k] - if not e then - e=format("[%s]",k) - elseif hexify then - e=format("&#%05X;",utfbyte(k)) - end - list[#list+1]=format(" <!ENTITY %s %q >",k,e) - end - end - local dt=root.dt - local n=dt[1].tg=="@pi@" and 2 or 1 - if #list>0 then - insert(dt,n,{ "\n" }) - insert(dt,n,{ - tg="@dt@", - dt={ format("Something [\n%s\n] ",concat(list)) }, - ns="", - special=true, - }) - insert(dt,n,{ "\n\n" }) - else - end - end -end -xml.all=xml.each -xml.insert=xml.insertafter -xml.inject=xml.injectafter -xml.after=xml.insertafter -xml.before=xml.insertbefore -xml.process=xml.each -xml.obsolete=xml.obsolete or {} -local obsolete=xml.obsolete -xml.strip_whitespace=xml.strip obsolete.strip_whitespace=xml.strip -xml.collect_elements=xml.collect obsolete.collect_elements=xml.collect -xml.delete_element=xml.delete obsolete.delete_element=xml.delete -xml.replace_element=xml.replace obsolete.replace_element=xml.replacet -xml.each_element=xml.each obsolete.each_element=xml.each -xml.process_elements=xml.process obsolete.process_elements=xml.process -xml.insert_element_after=xml.insertafter obsolete.insert_element_after=xml.insertafter -xml.insert_element_before=xml.insertbefore obsolete.insert_element_before=xml.insertbefore -xml.inject_element_after=xml.injectafter obsolete.inject_element_after=xml.injectafter -xml.inject_element_before=xml.injectbefore obsolete.inject_element_before=xml.injectbefore -xml.process_attributes=xml.processattributes obsolete.process_attributes=xml.processattributes -xml.collect_texts=xml.collecttexts obsolete.collect_texts=xml.collecttexts -xml.inject_element=xml.inject obsolete.inject_element=xml.inject -xml.remap_tag=xml.remaptag obsolete.remap_tag=xml.remaptag -xml.remap_name=xml.remapname obsolete.remap_name=xml.remapname -xml.remap_namespace=xml.remapnamespace obsolete.remap_namespace=xml.remapnamespace -function xml.cdata(e) - if e then - local dt=e.dt - if dt and #dt==1 then - local first=dt[1] - return first.tg=="@cd@" and first.dt[1] or "" - end - end - return "" -end -function xml.finalizers.xml.cdata(collected) - if collected then - local e=collected[1] - if e then - local dt=e.dt - if dt and #dt==1 then - local first=dt[1] - return first.tg=="@cd@" and first.dt[1] or "" - end - end - end - return "" -end -function xml.insertcomment(e,str,n) - table.insert(e.dt,n or 1,{ - tg="@cm@", - ns="", - special=true, - at={}, - dt={ str }, - }) -end -function xml.setcdata(e,str) - e.dt={ { - tg="@cd@", - ns="", - special=true, - at={}, - dt={ str }, - } } -end -function xml.separate(x,pattern) - local collected=xmlapplylpath(x,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local d=e.dt - if d==x then - report_xml("warning: xml.separate changes root") - x=d - end - local t,n={ "\n" },1 - local i,nd=1,#d - while i<=nd do - while i<=nd do - local di=d[i] - if type(di)=="string" then - if di=="\n" or find(di,"^%s+$") then - i=i+1 - else - d[i]=strip(di) - break - end - else - break - end - end - if i>nd then - break - end - t[n+1]="\n" - t[n+2]=d[i] - t[n+3]="\n" - n=n+3 - i=i+1 - end - t[n+1]="\n" - setmetatable(t,getmetatable(d)) - e.dt=t - end - end - return x -end -local helpers=xml.helpers or {} -xml.helpers=helpers -local function normal(e,action) - local edt=e.dt - if edt then - for i=1,#edt do - local str=edt[i] - if type(str)=="string" and str~="" then - edt[i]=action(str) - end - end - end -end -local function recurse(e,action) - local edt=e.dt - if edt then - for i=1,#edt do - local str=edt[i] - if type(str)~="string" then - recurse(str,action,recursive) - elseif str~="" then - edt[i]=action(str) - end - end - end -end -function helpers.recursetext(collected,action,recursive) - if recursive then - for i=1,#collected do - recurse(collected[i],action) - end - else - for i=1,#collected do - normal(collected[i],action) - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-xml"] = package.loaded["lxml-xml"] or true - --- original size: 10274, stripped down to: 7538 - -if not modules then modules={} end modules ['lxml-xml']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local concat=table.concat -local find,lower,upper=string.find,string.lower,string.upper -local xml=xml -local finalizers=xml.finalizers.xml -local xmlfilter=xml.filter -local xmltostring=xml.tostring -local xmlserialize=xml.serialize -local xmlcollected=xml.collected -local xmlnewhandlers=xml.newhandlers -local function first(collected) - return collected and collected[1] -end -local function last(collected) - return collected and collected[#collected] -end -local function all(collected) - return collected -end -local reverse=table.reversed -local function attribute(collected,name) - if collected and #collected>0 then - local at=collected[1].at - return at and at[name] - end -end -local function att(id,name) - local at=id.at - return at and at[name] -end -local function count(collected) - return collected and #collected or 0 -end -local function position(collected,n) - if not collected then - return 0 - end - local nc=#collected - if nc==0 then - return 0 - end - n=tonumber(n) or 0 - if n<0 then - return collected[nc+n+1] - elseif n>0 then - return collected[n] - else - return collected[1].mi or 0 - end -end -local function match(collected) - return collected and #collected>0 and collected[1].mi or 0 -end -local function index(collected) - return collected and #collected>0 and collected[1].ni or 0 -end -local function attributes(collected,arguments) - if collected and #collected>0 then - local at=collected[1].at - if arguments then - return at[arguments] - elseif next(at) then - return at - end - end -end -local function chainattribute(collected,arguments) - if collected and #collected>0 then - local e=collected[1] - while e do - local at=e.at - if at then - local a=at[arguments] - if a then - return a - end - else - break - end - e=e.__p__ - end - end - return "" -end -local function raw(collected) - if collected and #collected>0 then - local e=collected[1] or collected - return e and xmltostring(e) or "" - else - return "" - end -end -local xmltexthandler=xmlnewhandlers { - name="string", - initialize=function() - result={} - return result - end, - finalize=function() - return concat(result) - end, - handle=function(...) - result[#result+1]=concat {... } - end, - escape=false, -} -local function xmltotext(root) - local dt=root.dt - if not dt then - return "" - end - local nt=#dt - if nt==0 then - return "" - elseif nt==1 and type(dt[1])=="string" then - return dt[1] - else - return xmlserialize(root,xmltexthandler) or "" - end -end -local function text(collected) - if collected then - local e=collected[1] or collected - return e and xmltotext(e) or "" - else - return "" - end -end -local function texts(collected) - if not collected then - return {} - end - local nc=#collected - if nc==0 then - return {} - end - local t,n={},0 - for c=1,nc do - local e=collected[c] - if e and e.dt then - n=n+1 - t[n]=e.dt - end - end - return t -end -local function tag(collected,n) - if not collected then - return - end - local nc=#collected - if nc==0 then - return - end - local c - if n==0 or not n then - c=collected[1] - elseif n>1 then - c=collected[n] - else - c=collected[nc-n+1] - end - return c and c.tg -end -local function name(collected,n) - if not collected then - return - end - local nc=#collected - if nc==0 then - return - end - local c - if n==0 or not n then - c=collected[1] - elseif n>1 then - c=collected[n] - else - c=collected[nc-n+1] - end - if not c then - elseif c.ns=="" then - return c.tg - else - return c.ns..":"..c.tg - end -end -local function tags(collected,nonamespace) - if not collected then - return - end - local nc=#collected - if nc==0 then - return - end - local t,n={},0 - for c=1,nc do - local e=collected[c] - local ns,tg=e.ns,e.tg - n=n+1 - if nonamespace or ns=="" then - t[n]=tg - else - t[n]=ns..":"..tg - end - end - return t -end -local function empty(collected,spacesonly) - if not collected then - return true - end - local nc=#collected - if nc==0 then - return true - end - for c=1,nc do - local e=collected[c] - if e then - local edt=e.dt - if edt then - local n=#edt - if n==1 then - local edk=edt[1] - local typ=type(edk) - if typ=="table" then - return false - elseif edk~="" then - return false - elseif spacesonly and not find(edk,"%S") then - return false - end - elseif n>1 then - return false - end - end - end - end - return true -end -finalizers.first=first -finalizers.last=last -finalizers.all=all -finalizers.reverse=reverse -finalizers.elements=all -finalizers.default=all -finalizers.attribute=attribute -finalizers.att=att -finalizers.count=count -finalizers.position=position -finalizers.match=match -finalizers.index=index -finalizers.attributes=attributes -finalizers.chainattribute=chainattribute -finalizers.text=text -finalizers.texts=texts -finalizers.tag=tag -finalizers.name=name -finalizers.tags=tags -finalizers.empty=empty -function xml.first(id,pattern) - return first(xmlfilter(id,pattern)) -end -function xml.last(id,pattern) - return last(xmlfilter(id,pattern)) -end -function xml.count(id,pattern) - return count(xmlfilter(id,pattern)) -end -function xml.attribute(id,pattern,a,default) - return attribute(xmlfilter(id,pattern),a,default) -end -function xml.raw(id,pattern) - if pattern then - return raw(xmlfilter(id,pattern)) - else - return raw(id) - end -end -function xml.text(id,pattern) - if pattern then - local collected=xmlfilter(id,pattern) - return collected and #collected>0 and xmltotext(collected[1]) or "" - elseif id then - return xmltotext(id) or "" - else - return "" - end -end -xml.content=text -function xml.position(id,pattern,n) - return position(xmlfilter(id,pattern),n) -end -function xml.match(id,pattern) - return match(xmlfilter(id,pattern)) -end -function xml.empty(id,pattern,spacesonly) - return empty(xmlfilter(id,pattern),spacesonly) -end -xml.all=xml.filter -xml.index=xml.position -xml.found=xml.filter -local function totable(x) - local t={} - for e in xmlcollected(x[1] or x,"/*") do - t[e.tg]=xmltostring(e.dt) or "" - end - return next(t) and t or nil -end -xml.table=totable -finalizers.table=totable -local function textonly(e,t) - if e then - local edt=e.dt - if edt then - for i=1,#edt do - local e=edt[i] - if type(e)=="table" then - textonly(e,t) - else - t[#t+1]=e - end - end - end - end - return t -end -function xml.textonly(e) - return concat(textonly(e,{})) -end -function finalizers.lowerall(collected) - for c=1,#collected do - local e=collected[c] - if not e.special then - e.tg=lower(e.tg) - local eat=e.at - if eat then - local t={} - for k,v in next,eat do - t[lower(k)]=v - end - e.at=t - end - end - end -end -function finalizers.upperall(collected) - for c=1,#collected do - local e=collected[c] - if not e.special then - e.tg=upper(e.tg) - local eat=e.at - if eat then - local t={} - for k,v in next,eat do - t[upper(k)]=v - end - e.at=t - end - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-xml"] = package.loaded["trac-xml"] or true - --- original size: 6351, stripped down to: 4919 - -if not modules then modules={} end modules ['trac-xml']={ - version=1.001, - comment="companion to trac-log.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local formatters=string.formatters -local reporters=logs.reporters -local xmlserialize=xml.serialize -local xmlcollected=xml.collected -local xmltext=xml.text -local xmlfirst=xml.first -local function showhelp(specification,...) - local root=xml.convert(specification.helpinfo or "") - if not root then - return - end - local xs=xml.gethandlers("string") - xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end) - xml.sethandlersfunction(xs,"ref",function(e,handler) handler.handle("--"..e.at.name) end) - local wantedcategories=select("#",...)==0 and true or table.tohash {... } - local nofcategories=xml.count(root,"/application/flags/category") - local report=specification.report - for category in xmlcollected(root,"/application/flags/category") do - local categoryname=category.at.name or "" - if wantedcategories==true or wantedcategories[categoryname] then - if nofcategories>1 then - report("%s options:",categoryname) - report() - end - for subcategory in xmlcollected(category,"/subcategory") do - for flag in xmlcollected(subcategory,"/flag") do - local name=flag.at.name - local value=flag.at.value - local short=xmltext(xmlfirst(flag,"/short")) - if value then - report("--%-20s %s",formatters["%s=%s"](name,value),short) - else - report("--%-20s %s",name,short) - end - end - report() - end - end - end - for category in xmlcollected(root,"/application/examples/category") do - local title=xmltext(xmlfirst(category,"/title")) - if title and title~="" then - report() - report(title) - report() - end - for subcategory in xmlcollected(category,"/subcategory") do - for example in xmlcollected(subcategory,"/example") do - local command=xmltext(xmlfirst(example,"/command")) - local comment=xmltext(xmlfirst(example,"/comment")) - report(command) - end - report() - end - end - for comment in xmlcollected(root,"/application/comments/comment") do - local comment=xmltext(comment) - report() - report(comment) - report() - end -end -local reporthelp=reporters.help -local exporthelp=reporters.export -local function xmlfound(t) - local helpinfo=t.helpinfo - if type(helpinfo)=="table" then - return false - end - if type(helpinfo)~="string" then - helpinfo="Warning: no helpinfo found." - t.helpinfo=helpinfo - return false - end - if string.find(helpinfo,".xml$") then - local ownscript=environment.ownscript - local helpdata=false - if ownscript then - local helpfile=file.join(file.pathpart(ownscript),helpinfo) - helpdata=io.loaddata(helpfile) - if helpdata=="" then - helpdata=false - end - end - if not helpdata then - local helpfile=resolvers.findfile(helpinfo,"tex") - helpdata=helpfile and io.loaddata(helpfile) - end - if helpdata and helpdata~="" then - helpinfo=helpdata - else - helpinfo=formatters["Warning: help file %a is not found."](helpinfo) - end - end - t.helpinfo=helpinfo - return string.find(t.helpinfo,"^<%?xml") and true or false -end -function reporters.help(t,...) - if xmlfound(t) then - showhelp(t,...) - else - reporthelp(t,...) - end -end -function reporters.export(t,methods,filename) - if not xmlfound(t) then - return exporthelp(t) - end - if not methods or methods=="" then - methods=environment.arguments["exporthelp"] - end - if not filename or filename=="" then - filename=environment.files[1] - end - dofile(resolvers.findfile("trac-exp.lua","tex")) - local exporters=logs.exporters - if not exporters or not methods then - return exporthelp(t) - end - if methods=="all" then - methods=table.keys(exporters) - elseif type(methods)=="string" then - methods=utilities.parsers.settings_to_array(methods) - else - return exporthelp(t) - end - if type(filename)~="string" or filename=="" then - filename=false - elseif file.pathpart(filename)=="" then - t.report("export file %a will not be saved on the current path (safeguard)",filename) - return - end - for i=1,#methods do - local method=methods[i] - local exporter=exporters[method] - if exporter then - local result=exporter(t,method) - if result and result~="" then - if filename then - local fullname=file.replacesuffix(filename,method) - t.report("saving export in %a",fullname) - io.savedata(fullname,result) - else - reporters.lines(t,result) - end - else - t.report("no output from exporter %a",method) - end - else - t.report("unknown exporter %a",method) - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-ini"] = package.loaded["data-ini"] or true - --- original size: 7898, stripped down to: 5501 - -if not modules then modules={} end modules ['data-ini']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char -local next,type=next,type -local filedirname,filebasename,filejoin=file.dirname,file.basename,file.join -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end) -local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end) -local report_initialization=logs.reporter("resolvers","initialization") -local ostype,osname,ossetenv,osgetenv=os.type,os.name,os.setenv,os.getenv -resolvers=resolvers or {} -local resolvers=resolvers -texconfig.kpse_init=false -texconfig.shell_escape='t' -if not (environment and environment.default_texmfcnf) and kpse and kpse.default_texmfcnf then - local default_texmfcnf=kpse.default_texmfcnf() - default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:") - default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:") - default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:") - default_texmfcnf=gsub(default_texmfcnf,"$HOME","home:") - environment.default_texmfcnf=default_texmfcnf -end -kpse={ original=kpse } -setmetatable(kpse,{ - __index=function(kp,name) - report_initialization("fatal error: kpse library is accessed (key: %s)",name) - os.exit() - end -} ) -do - local osfontdir=osgetenv("OSFONTDIR") - if osfontdir and osfontdir~="" then - elseif osname=="windows" then - ossetenv("OSFONTDIR","c:/windows/fonts//") - elseif osname=="macosx" then - ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//") - end -end -do - local homedir=osgetenv(ostype=="windows" and 'USERPROFILE' or 'HOME') or '' - if not homedir or homedir=="" then - homedir=char(127) - end - homedir=file.collapsepath(homedir) - ossetenv("HOME",homedir) - ossetenv("USERPROFILE",homedir) - environment.homedir=homedir -end -do - local args=environment.originalarguments or arg - if not environment.ownmain then - environment.ownmain=status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex" - end - local ownbin=environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex" - local ownpath=environment.ownpath or os.selfdir - ownbin=file.collapsepath(ownbin) - ownpath=file.collapsepath(ownpath) - if not ownpath or ownpath=="" or ownpath=="unset" then - ownpath=args[-1] or arg[-1] - ownpath=ownpath and filedirname(gsub(ownpath,"\\","/")) - if not ownpath or ownpath=="" then - ownpath=args[-0] or arg[-0] - ownpath=ownpath and filedirname(gsub(ownpath,"\\","/")) - end - local binary=ownbin - if not ownpath or ownpath=="" then - ownpath=ownpath and filedirname(binary) - end - if not ownpath or ownpath=="" then - if os.binsuffix~="" then - binary=file.replacesuffix(binary,os.binsuffix) - end - local path=osgetenv("PATH") - if path then - for p in gmatch(path,"[^"..io.pathseparator.."]+") do - local b=filejoin(p,binary) - if lfs.isfile(b) then - local olddir=lfs.currentdir() - if lfs.chdir(p) then - local pp=lfs.currentdir() - if trace_locating and p~=pp then - report_initialization("following symlink %a to %a",p,pp) - end - ownpath=pp - lfs.chdir(olddir) - else - if trace_locating then - report_initialization("unable to check path %a",p) - end - ownpath=p - end - break - end - end - end - end - if not ownpath or ownpath=="" then - ownpath="." - report_initialization("forcing fallback to ownpath %a",ownpath) - elseif trace_locating then - report_initialization("using ownpath %a",ownpath) - end - end - environment.ownbin=ownbin - environment.ownpath=ownpath -end -resolvers.ownpath=environment.ownpath -function resolvers.getownpath() - return environment.ownpath -end -do - local ownpath=environment.ownpath or dir.current() - if ownpath then - ossetenv('SELFAUTOLOC',file.collapsepath(ownpath)) - ossetenv('SELFAUTODIR',file.collapsepath(ownpath.."/..")) - ossetenv('SELFAUTOPARENT',file.collapsepath(ownpath.."/../..")) - else - report_initialization("error: unable to locate ownpath") - os.exit() - end -end -local texos=environment.texos or osgetenv("TEXOS") -local texmfos=environment.texmfos or osgetenv('SELFAUTODIR') -if not texos or texos=="" then - texos=file.basename(texmfos) -end -ossetenv('TEXMFOS',texmfos) -ossetenv('TEXOS',texos) -ossetenv('SELFAUTOSYSTEM',os.platform) -environment.texos=texos -environment.texmfos=texmfos -local texroot=environment.texroot or osgetenv("TEXROOT") -if not texroot or texroot=="" then - texroot=osgetenv('SELFAUTOPARENT') - ossetenv('TEXROOT',texroot) -end -environment.texroot=file.collapsepath(texroot) -if profiler then - directives.register("system.profile",function() - profiler.start("luatex-profile.log") - end) -end -if not resolvers.resolve then - function resolvers.resolve (s) return s end - function resolvers.unresolve(s) return s end - function resolvers.repath (s) return s end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-exp"] = package.loaded["data-exp"] or true - --- original size: 15303, stripped down to: 9716 - -if not modules then modules={} end modules ['data-exp']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local format,find,gmatch,lower,char,sub=string.format,string.find,string.gmatch,string.lower,string.char,string.sub -local concat,sort=table.concat,table.sort -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local Ct,Cs,Cc,Carg,P,C,S=lpeg.Ct,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.P,lpeg.C,lpeg.S -local type,next=type,next -local ostype=os.type -local collapsepath=file.collapsepath -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end) -local report_expansions=logs.reporter("resolvers","expansions") -local resolvers=resolvers -local function f_both(a,b) - local t,n={},0 - for sb in gmatch(b,"[^,]+") do - for sa in gmatch(a,"[^,]+") do - n=n+1;t[n]=sa..sb - end - end - return concat(t,",") -end -local comma=P(",") -local nocomma=(1-comma)^1 -local docomma=comma^1/"," -local before=Cs((nocomma*Carg(1)+docomma)^0) -local after=Cs((Carg(1)*nocomma+docomma)^0) -local both=Cs(((C(nocomma)*Carg(1))/function(a,b) return lpegmatch(before,b,1,a) end+docomma)^0) -local function f_first (a,b) return lpegmatch(after,b,1,a) end -local function f_second(a,b) return lpegmatch(before,a,1,b) end -local function f_both (a,b) return lpegmatch(both,b,1,a) end -local left=P("{") -local right=P("}") -local var=P((1-S("{}" ))^0) -local set=P((1-S("{},"))^0) -local other=P(1) -local l_first=Cs((Cc("{")*(C(set)*left*C(var)*right/f_first)*Cc("}")+other )^0 ) -local l_second=Cs((Cc("{")*(left*C(var)*right*C(set)/f_second)*Cc("}")+other )^0 ) -local l_both=Cs((Cc("{")*(left*C(var)*right*left*C(var)*right/f_both)*Cc("}")+other )^0 ) -local l_rest=Cs((left*var*(left/"")*var*(right/"")*var*right+other )^0 ) -local stripper_1=lpeg.stripper ("{}@") -local replacer_1=lpeg.replacer { { ",}",",@}" },{ "{,","{@," },} -local function splitpathexpr(str,newlist,validate) - if trace_expansions then - report_expansions("expanding variable %a",str) - end - local t,ok,done=newlist or {},false,false - local n=#t - str=lpegmatch(replacer_1,str) - repeat - local old=str - repeat - local old=str - str=lpegmatch(l_first,str) - until old==str - repeat - local old=str - str=lpegmatch(l_second,str) - until old==str - repeat - local old=str - str=lpegmatch(l_both,str) - until old==str - repeat - local old=str - str=lpegmatch(l_rest,str) - until old==str - until old==str - str=lpegmatch(stripper_1,str) - if validate then - for s in gmatch(str,"[^,]+") do - s=validate(s) - if s then - n=n+1 - t[n]=s - end - end - else - for s in gmatch(str,"[^,]+") do - n=n+1 - t[n]=s - end - end - if trace_expansions then - for k=1,#t do - report_expansions("% 4i: %s",k,t[k]) - end - end - return t -end -local function validate(s) - s=collapsepath(s) - return s~="" and not find(s,"^!*unset/*$") and s -end -resolvers.validatedpath=validate -function resolvers.expandedpathfromlist(pathlist) - local newlist={} - for k=1,#pathlist do - splitpathexpr(pathlist[k],newlist,validate) - end - return newlist -end -local cleanup=lpeg.replacer { - { "!","" }, - { "\\","/" }, -} -function resolvers.cleanpath(str) - local doslashes=(P("\\")/"/"+1)^0 - local donegation=(P("!")/"" )^0 - local homedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "") - if homedir=="~" or homedir=="" or not lfs.isdir(homedir) then - if trace_expansions then - report_expansions("no home dir set, ignoring dependent paths") - end - function resolvers.cleanpath(str) - if not str or find(str,"~") then - return "" - else - return lpegmatch(cleanup,str) - end - end - else - local dohome=((P("~")+P("$HOME"))/homedir)^0 - local cleanup=Cs(donegation*dohome*doslashes) - function resolvers.cleanpath(str) - return str and lpegmatch(cleanup,str) or "" - end - end - return resolvers.cleanpath(str) -end -local expandhome=P("~")/"$HOME" -local dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/"" -local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/"" -local dostring=(expandhome+1 )^0 -local stripper=Cs( - lpegpatterns.unspacer*(dosingle+dodouble+dostring)*lpegpatterns.unspacer -) -function resolvers.checkedvariable(str) - return type(str)=="string" and lpegmatch(stripper,str) or str -end -local cache={} -local splitter=lpeg.tsplitat(";") -local backslashswapper=lpeg.replacer("\\","/") -local function splitconfigurationpath(str) - if str then - local found=cache[str] - if not found then - if str=="" then - found={} - else - local split=lpegmatch(splitter,lpegmatch(backslashswapper,str)) - found={} - local noffound=0 - for i=1,#split do - local s=split[i] - if not find(s,"^{*unset}*") then - noffound=noffound+1 - found[noffound]=s - end - end - if trace_expansions then - report_expansions("splitting path specification %a",str) - for k=1,noffound do - report_expansions("% 4i: %s",k,found[k]) - end - end - cache[str]=found - end - end - return found - end -end -resolvers.splitconfigurationpath=splitconfigurationpath -function resolvers.splitpath(str) - if type(str)=='table' then - return str - else - return splitconfigurationpath(str) - end -end -function resolvers.joinpath(str) - if type(str)=='table' then - return file.joinpath(str) - else - return str - end -end -local attributes,directory=lfs.attributes,lfs.dir -local weird=P(".")^1+lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t")) -local timer={} -local scanned={} -local nofscans=0 -local scancache={} -local function scan(files,spec,path,n,m,r) - local full=(path=="" and spec) or (spec..path..'/') - local dirs={} - local nofdirs=0 - for name in directory(full) do - if not lpegmatch(weird,name) then - local mode=attributes(full..name,'mode') - if mode=='file' then - n=n+1 - local f=files[name] - if f then - if type(f)=='string' then - files[name]={ f,path } - else - f[#f+1]=path - end - else - files[name]=path - local lower=lower(name) - if name~=lower then - files["remap:"..lower]=name - r=r+1 - end - end - elseif mode=='directory' then - m=m+1 - nofdirs=nofdirs+1 - if path~="" then - dirs[nofdirs]=path..'/'..name - else - dirs[nofdirs]=name - end - end - end - end - if nofdirs>0 then - sort(dirs) - for i=1,nofdirs do - files,n,m,r=scan(files,spec,dirs[i],n,m,r) - end - end - scancache[sub(full,1,-2)]=files - return files,n,m,r -end -local fullcache={} -function resolvers.scanfiles(path,branch,usecache) - statistics.starttiming(timer) - local realpath=resolvers.resolve(path) - if usecache then - local files=fullcache[realpath] - if files then - if trace_locating then - report_expansions("using caches scan of path %a, branch %a",path,branch or path) - end - return files - end - end - if trace_locating then - report_expansions("scanning path %a, branch %a",path,branch or path) - end - local files,n,m,r=scan({},realpath..'/',"",0,0,0) - files.__path__=path - files.__files__=n - files.__directories__=m - files.__remappings__=r - if trace_locating then - report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r) - end - if usecache then - scanned[#scanned+1]=realpath - fullcache[realpath]=files - end - nofscans=nofscans+1 - statistics.stoptiming(timer) - return files -end -local function simplescan(files,spec,path) - local full=(path=="" and spec) or (spec..path..'/') - local dirs={} - local nofdirs=0 - for name in directory(full) do - if not lpegmatch(weird,name) then - local mode=attributes(full..name,'mode') - if mode=='file' then - if not files[name] then - files[name]=path - end - elseif mode=='directory' then - nofdirs=nofdirs+1 - if path~="" then - dirs[nofdirs]=path..'/'..name - else - dirs[nofdirs]=name - end - end - end - end - if nofdirs>0 then - sort(dirs) - for i=1,nofdirs do - files=simplescan(files,spec,dirs[i]) - end - end - return files -end -local simplecache={} -local nofsharedscans=0 -function resolvers.simplescanfiles(path,branch,usecache) - statistics.starttiming(timer) - local realpath=resolvers.resolve(path) - if usecache then - local files=simplecache[realpath] - if not files then - files=scancache[realpath] - if files then - nofsharedscans=nofsharedscans+1 - end - end - if files then - if trace_locating then - report_expansions("using caches scan of path %a, branch %a",path,branch or path) - end - return files - end - end - if trace_locating then - report_expansions("scanning path %a, branch %a",path,branch or path) - end - local files=simplescan({},realpath..'/',"") - if trace_locating then - report_expansions("%s files found",table.count(files)) - end - if usecache then - scanned[#scanned+1]=realpath - simplecache[realpath]=files - end - nofscans=nofscans+1 - statistics.stoptiming(timer) - return files -end -function resolvers.scandata() - table.sort(scanned) - return { - n=nofscans, - shared=nofsharedscans, - time=statistics.elapsedtime(timer), - paths=scanned, - } -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-env"] = package.loaded["data-env"] or true - --- original size: 8769, stripped down to: 6490 - -if not modules then modules={} end modules ['data-env']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local lower,gsub=string.lower,string.gsub -local resolvers=resolvers -local allocate=utilities.storage.allocate -local setmetatableindex=table.setmetatableindex -local suffixonly=file.suffixonly -local formats=allocate() -local suffixes=allocate() -local dangerous=allocate() -local suffixmap=allocate() -resolvers.formats=formats -resolvers.suffixes=suffixes -resolvers.dangerous=dangerous -resolvers.suffixmap=suffixmap -local luasuffixes=utilities.lua.suffixes -local relations=allocate { - core={ - ofm={ - names={ "ofm","omega font metric","omega font metrics" }, - variable='OFMFONTS', - suffixes={ 'ofm','tfm' }, - }, - ovf={ - names={ "ovf","omega virtual font","omega virtual fonts" }, - variable='OVFFONTS', - suffixes={ 'ovf','vf' }, - }, - tfm={ - names={ "tfm","tex font metric","tex font metrics" }, - variable='TFMFONTS', - suffixes={ 'tfm' }, - }, - vf={ - names={ "vf","virtual font","virtual fonts" }, - variable='VFFONTS', - suffixes={ 'vf' }, - }, - otf={ - names={ "otf","opentype","opentype font","opentype fonts"}, - variable='OPENTYPEFONTS', - suffixes={ 'otf' }, - }, - ttf={ - names={ "ttf","truetype","truetype font","truetype fonts","truetype collection","truetype collections","truetype dictionary","truetype dictionaries" }, - variable='TTFONTS', - suffixes={ 'ttf','ttc','dfont' }, - }, - afm={ - names={ "afm","adobe font metric","adobe font metrics" }, - variable="AFMFONTS", - suffixes={ "afm" }, - }, - pfb={ - names={ "pfb","type1","type 1","type1 font","type 1 font","type1 fonts","type 1 fonts" }, - variable='T1FONTS', - suffixes={ 'pfb','pfa' }, - }, - fea={ - names={ "fea","font feature","font features","font feature file","font feature files" }, - variable='FONTFEATURES', - suffixes={ 'fea' }, - }, - cid={ - names={ "cid","cid map","cid maps","cid file","cid files" }, - variable='FONTCIDMAPS', - suffixes={ 'cid','cidmap' }, - }, - fmt={ - names={ "fmt","format","tex format" }, - variable='TEXFORMATS', - suffixes={ 'fmt' }, - }, - mem={ - names={ 'mem',"metapost format" }, - variable='MPMEMS', - suffixes={ 'mem' }, - }, - mp={ - names={ "mp" }, - variable='MPINPUTS', - suffixes={ 'mp','mpvi','mpiv','mpii' }, - }, - tex={ - names={ "tex" }, - variable='TEXINPUTS', - suffixes={ 'tex',"mkvi","mkiv","mkii" }, - }, - icc={ - names={ "icc","icc profile","icc profiles" }, - variable='ICCPROFILES', - suffixes={ 'icc' }, - }, - texmfscripts={ - names={ "texmfscript","texmfscripts","script","scripts" }, - variable='TEXMFSCRIPTS', - suffixes={ 'lua','rb','pl','py' }, - }, - lua={ - names={ "lua" }, - variable='LUAINPUTS', - suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc }, - }, - lib={ - names={ "lib" }, - variable='CLUAINPUTS', - suffixes=os.libsuffix and { os.libsuffix } or { 'dll','so' }, - }, - bib={ - names={ 'bib' }, - suffixes={ 'bib' }, - }, - bst={ - names={ 'bst' }, - suffixes={ 'bst' }, - }, - fontconfig={ - names={ 'fontconfig','fontconfig file','fontconfig files' }, - variable='FONTCONFIG_PATH', - }, - }, - obsolete={ - enc={ - names={ "enc","enc files","enc file","encoding files","encoding file" }, - variable='ENCFONTS', - suffixes={ 'enc' }, - }, - map={ - names={ "map","map files","map file" }, - variable='TEXFONTMAPS', - suffixes={ 'map' }, - }, - lig={ - names={ "lig files","lig file","ligature file","ligature files" }, - variable='LIGFONTS', - suffixes={ 'lig' }, - }, - opl={ - names={ "opl" }, - variable='OPLFONTS', - suffixes={ 'opl' }, - }, - ovp={ - names={ "ovp" }, - variable='OVPFONTS', - suffixes={ 'ovp' }, - }, - }, - kpse={ - base={ - names={ 'base',"metafont format" }, - variable='MFBASES', - suffixes={ 'base','bas' }, - }, - cmap={ - names={ 'cmap','cmap files','cmap file' }, - variable='CMAPFONTS', - suffixes={ 'cmap' }, - }, - cnf={ - names={ 'cnf' }, - suffixes={ 'cnf' }, - }, - web={ - names={ 'web' }, - suffixes={ 'web','ch' } - }, - cweb={ - names={ 'cweb' }, - suffixes={ 'w','web','ch' }, - }, - gf={ - names={ 'gf' }, - suffixes={ '<resolution>gf' }, - }, - mf={ - names={ 'mf' }, - variable='MFINPUTS', - suffixes={ 'mf' }, - }, - mft={ - names={ 'mft' }, - suffixes={ 'mft' }, - }, - pk={ - names={ 'pk' }, - suffixes={ '<resolution>pk' }, - }, - }, -} -resolvers.relations=relations -function resolvers.updaterelations() - for category,categories in next,relations do - for name,relation in next,categories do - local rn=relation.names - local rv=relation.variable - local rs=relation.suffixes - if rn and rv then - for i=1,#rn do - local rni=lower(gsub(rn[i]," ","")) - formats[rni]=rv - if rs then - suffixes[rni]=rs - for i=1,#rs do - local rsi=rs[i] - suffixmap[rsi]=rni - end - end - end - end - if rs then - end - end - end -end -resolvers.updaterelations() -local function simplified(t,k) - return k and rawget(t,lower(gsub(k," ",""))) or nil -end -setmetatableindex(formats,simplified) -setmetatableindex(suffixes,simplified) -setmetatableindex(suffixmap,simplified) -function resolvers.suffixofformat(str) - local s=suffixes[str] - return s and s[1] or "" -end -function resolvers.suffixofformat(str) - return suffixes[str] or {} -end -for name,format in next,formats do - dangerous[name]=true -end -dangerous.tex=nil -function resolvers.formatofvariable(str) - return formats[str] or '' -end -function resolvers.formatofsuffix(str) - return suffixmap[suffixonly(str)] or 'tex' -end -function resolvers.variableofformat(str) - return formats[str] or '' -end -function resolvers.variableofformatorsuffix(str) - local v=formats[str] - if v then - return v - end - v=suffixmap[suffixonly(str)] - if v then - return formats[v] - end - return '' -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-tmp"] = package.loaded["data-tmp"] or true - --- original size: 15532, stripped down to: 11648 - -if not modules then modules={} end modules ['data-tmp']={ - version=1.100, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,lower,gsub,concat=string.format,string.lower,string.gsub,table.concat -local concat,serialize,serializetofile=table.concat,table.serialize,table.tofile -local mkdirs,isdir,isfile=dir.mkdirs,lfs.isdir,lfs.isfile -local addsuffix,is_writable,is_readable=file.addsuffix,file.is_writable,file.is_readable -local formatters=string.formatters -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end) -local report_caches=logs.reporter("resolvers","caches") -local report_resolvers=logs.reporter("resolvers","caching") -local resolvers=resolvers -local directive_cleanup=false directives.register("system.compile.cleanup",function(v) directive_cleanup=v end) -local directive_strip=false directives.register("system.compile.strip",function(v) directive_strip=v end) -local compile=utilities.lua.compile -function utilities.lua.compile(luafile,lucfile,cleanup,strip) - if cleanup==nil then cleanup=directive_cleanup end - if strip==nil then strip=directive_strip end - return compile(luafile,lucfile,cleanup,strip) -end -caches=caches or {} -local caches=caches -local luasuffixes=utilities.lua.suffixes -caches.base=caches.base or "luatex-cache" -caches.more=caches.more or "context" -caches.direct=false -caches.tree=false -caches.force=true -caches.ask=false -caches.relocate=false -caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } -local writable,readables,usedreadables=nil,{},{} -local function identify() - local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE") - if texmfcaches then - for k=1,#texmfcaches do - local cachepath=texmfcaches[k] - if cachepath~="" then - cachepath=resolvers.resolve(cachepath) - cachepath=resolvers.cleanpath(cachepath) - cachepath=file.collapsepath(cachepath) - local valid=isdir(cachepath) - if valid then - if is_readable(cachepath) then - readables[#readables+1]=cachepath - if not writable and is_writable(cachepath) then - writable=cachepath - end - end - elseif not writable and caches.force then - local cacheparent=file.dirname(cachepath) - if is_writable(cacheparent) and true then - if not caches.ask or io.ask(format("\nShould I create the cache path %s?",cachepath),"no",{ "yes","no" })=="yes" then - mkdirs(cachepath) - if isdir(cachepath) and is_writable(cachepath) then - report_caches("path %a created",cachepath) - writable=cachepath - readables[#readables+1]=cachepath - end - end - end - end - end - end - end - local texmfcaches=caches.defaults - if texmfcaches then - for k=1,#texmfcaches do - local cachepath=texmfcaches[k] - cachepath=resolvers.expansion(cachepath) - if cachepath~="" then - cachepath=resolvers.resolve(cachepath) - cachepath=resolvers.cleanpath(cachepath) - local valid=isdir(cachepath) - if valid and is_readable(cachepath) then - if not writable and is_writable(cachepath) then - readables[#readables+1]=cachepath - writable=cachepath - break - end - end - end - end - end - if not writable then - report_caches("fatal error: there is no valid writable cache path defined") - os.exit() - elseif #readables==0 then - report_caches("fatal error: there is no valid readable cache path defined") - os.exit() - end - writable=dir.expandname(resolvers.cleanpath(writable)) - local base,more,tree=caches.base,caches.more,caches.tree or caches.treehash() - if tree then - caches.tree=tree - writable=mkdirs(writable,base,more,tree) - for i=1,#readables do - readables[i]=file.join(readables[i],base,more,tree) - end - else - writable=mkdirs(writable,base,more) - for i=1,#readables do - readables[i]=file.join(readables[i],base,more) - end - end - if trace_cache then - for i=1,#readables do - report_caches("using readable path %a (order %s)",readables[i],i) - end - report_caches("using writable path %a",writable) - end - identify=function() - return writable,readables - end - return writable,readables -end -function caches.usedpaths(separator) - local writable,readables=identify() - if #readables>1 then - local result={} - local done={} - for i=1,#readables do - local readable=readables[i] - if readable==writable then - done[readable]=true - result[#result+1]=formatters["readable+writable: %a"](readable) - elseif usedreadables[i] then - done[readable]=true - result[#result+1]=formatters["readable: %a"](readable) - end - end - if not done[writable] then - result[#result+1]=formatters["writable: %a"](writable) - end - return concat(result,separator or " | ") - else - return writable or "?" - end -end -function caches.configfiles() - return concat(resolvers.instance.specification,";") -end -function caches.hashed(tree) - tree=gsub(tree,"[\\/]+$","") - tree=lower(tree) - local hash=md5.hex(tree) - if trace_cache or trace_locating then - report_caches("hashing tree %a, hash %a",tree,hash) - end - return hash -end -function caches.treehash() - local tree=caches.configfiles() - if not tree or tree=="" then - return false - else - return caches.hashed(tree) - end -end -local r_cache,w_cache={},{} -local function getreadablepaths(...) - local tags={... } - local hash=concat(tags,"/") - local done=r_cache[hash] - if not done then - local writable,readables=identify() - if #tags>0 then - done={} - for i=1,#readables do - done[i]=file.join(readables[i],...) - end - else - done=readables - end - r_cache[hash]=done - end - return done -end -local function getwritablepath(...) - local tags={... } - local hash=concat(tags,"/") - local done=w_cache[hash] - if not done then - local writable,readables=identify() - if #tags>0 then - done=mkdirs(writable,...) - else - done=writable - end - w_cache[hash]=done - end - return done -end -caches.getreadablepaths=getreadablepaths -caches.getwritablepath=getwritablepath -function caches.getfirstreadablefile(filename,...) - local rd=getreadablepaths(...) - for i=1,#rd do - local path=rd[i] - local fullname=file.join(path,filename) - if is_readable(fullname) then - usedreadables[i]=true - return fullname,path - end - end - return caches.setfirstwritablefile(filename,...) -end -function caches.getfirstreadablefile_TEST_ME_FIRST(filename,...) - local fullname,path=caches.setfirstwritablefile(filename,...) - if is_readable(fullname) then - return fullname,path - end - local rd=getreadablepaths(...) - for i=1,#rd do - local path=rd[i] - local fullname=file.join(path,filename) - if is_readable(fullname) then - usedreadables[i]=true - return fullname,path - end - end - return fullname,path -end -function caches.setfirstwritablefile(filename,...) - local wr=getwritablepath(...) - local fullname=file.join(wr,filename) - return fullname,wr -end -function caches.define(category,subcategory) - return function() - return getwritablepath(category,subcategory) - end -end -function caches.setluanames(path,name) - return format("%s/%s.%s",path,name,luasuffixes.tma),format("%s/%s.%s",path,name,luasuffixes.tmc) -end -function caches.loaddata(readables,name) - if type(readables)=="string" then - readables={ readables } - end - for i=1,#readables do - local path=readables[i] - local tmaname,tmcname=caches.setluanames(path,name) - local loader=false - if isfile(tmcname) then - loader=loadfile(tmcname) - end - if not loader and isfile(tmaname) then - utilities.lua.compile(tmaname,tmcname) - if isfile(tmcname) then - loader=loadfile(tmcname) - end - if not loader then - loader=loadfile(tmaname) - end - end - if loader then - loader=loader() - collectgarbage("step") - return loader - end - end - return false -end -function caches.is_writable(filepath,filename) - local tmaname,tmcname=caches.setluanames(filepath,filename) - return is_writable(tmaname) -end -local saveoptions={ compact=true } -function caches.savedata(filepath,filename,data,raw) - local tmaname,tmcname=caches.setluanames(filepath,filename) - local reduce,simplify=true,true - if raw then - reduce,simplify=false,false - end - data.cache_uuid=os.uuid() - if caches.direct then - file.savedata(tmaname,serialize(data,true,saveoptions)) - else - serializetofile(tmaname,data,true,saveoptions) - end - utilities.lua.compile(tmaname,tmcname) -end -local content_state={} -function caches.contentstate() - return content_state or {} -end -function caches.loadcontent(cachename,dataname) - local name=caches.hashed(cachename) - local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees") - local filename=file.join(path,name) - local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua)) - if blob then - local data=blob() - if data and data.content then - if data.type==dataname then - if data.version==resolvers.cacheversion then - content_state[#content_state+1]=data.uuid - if trace_locating then - report_resolvers("loading %a for %a from %a",dataname,cachename,filename) - end - return data.content - else - report_resolvers("skipping %a for %a from %a (version mismatch)",dataname,cachename,filename) - end - else - report_resolvers("skipping %a for %a from %a (datatype mismatch)",dataname,cachename,filename) - end - elseif trace_locating then - report_resolvers("skipping %a for %a from %a (no content)",dataname,cachename,filename) - end - elseif trace_locating then - report_resolvers("skipping %a for %a from %a (invalid file)",dataname,cachename,filename) - end -end -function caches.collapsecontent(content) - for k,v in next,content do - if type(v)=="table" and #v==1 then - content[k]=v[1] - end - end -end -function caches.savecontent(cachename,dataname,content) - local name=caches.hashed(cachename) - local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees") - local filename=file.join(path,name) - local luaname=addsuffix(filename,luasuffixes.lua) - local lucname=addsuffix(filename,luasuffixes.luc) - if trace_locating then - report_resolvers("preparing %a for %a",dataname,cachename) - end - local data={ - type=dataname, - root=cachename, - version=resolvers.cacheversion, - date=os.date("%Y-%m-%d"), - time=os.date("%H:%M:%S"), - content=content, - uuid=os.uuid(), - } - local ok=io.savedata(luaname,serialize(data,true)) - if ok then - if trace_locating then - report_resolvers("category %a, cachename %a saved in %a",dataname,cachename,luaname) - end - if utilities.lua.compile(luaname,lucname) then - if trace_locating then - report_resolvers("%a compiled to %a",dataname,lucname) - end - return true - else - if trace_locating then - report_resolvers("compiling failed for %a, deleting file %a",dataname,lucname) - end - os.remove(lucname) - end - elseif trace_locating then - report_resolvers("unable to save %a in %a (access error)",dataname,luaname) - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-met"] = package.loaded["data-met"] or true - --- original size: 5453, stripped down to: 4007 - -if not modules then modules={} end modules ['data-met']={ - version=1.100, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local find,format=string.find,string.format -local sequenced=table.sequenced -local addurlscheme,urlhashed=url.addscheme,url.hashed -local getcurrentdir=lfs.currentdir -local trace_locating=false -local trace_methods=false -trackers.register("resolvers.locating",function(v) trace_methods=v end) -trackers.register("resolvers.methods",function(v) trace_methods=v end) -local report_methods=logs.reporter("resolvers","methods") -local allocate=utilities.storage.allocate -local resolvers=resolvers -local registered={} -local function splitmethod(filename) - if not filename then - return { scheme="unknown",original=filename } - end - if type(filename)=="table" then - return filename - end - filename=file.collapsepath(filename,".") - if not find(filename,"://") then - return { scheme="file",path=filename,original=filename,filename=filename } - end - local specification=url.hashed(filename) - if not specification.scheme or specification.scheme=="" then - return { scheme="file",path=filename,original=filename,filename=filename } - else - return specification - end -end -resolvers.splitmethod=splitmethod -local function methodhandler(what,first,...) - local method=registered[what] - if method then - local how,namespace=method.how,method.namespace - if how=="uri" or how=="url" then - local specification=splitmethod(first) - local scheme=specification.scheme - local resolver=namespace and namespace[scheme] - if resolver then - if trace_methods then - report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first) - end - return resolver(specification,...) - else - resolver=namespace.default or namespace.file - if resolver then - if trace_methods then - report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first) - end - return resolver(specification,...) - elseif trace_methods then - report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset") - end - end - elseif how=="tag" then - local resolver=namespace and namespace[first] - if resolver then - if trace_methods then - report_methods("resolving, method %a, how %a, tag %a",what,how,first) - end - return resolver(...) - else - resolver=namespace.default or namespace.file - if resolver then - if trace_methods then - report_methods("resolving, method %a, how %a, tag %a",what,how,"default") - end - return resolver(...) - elseif trace_methods then - report_methods("resolving, method %a, how %a, tag %a",what,how,"unset") - end - end - end - else - report_methods("resolving, invalid method %a") - end -end -resolvers.methodhandler=methodhandler -function resolvers.registermethod(name,namespace,how) - registered[name]={ how=how or "tag",namespace=namespace } - namespace["byscheme"]=function(scheme,filename,...) - if scheme=="file" then - return methodhandler(name,filename,...) - else - return methodhandler(name,addurlscheme(filename,scheme),...) - end - end -end -local concatinators=allocate { notfound=file.join } -local locators=allocate { notfound=function() end } -local hashers=allocate { notfound=function() end } -local generators=allocate { notfound=function() end } -resolvers.concatinators=concatinators -resolvers.locators=locators -resolvers.hashers=hashers -resolvers.generators=generators -local registermethod=resolvers.registermethod -registermethod("concatinators",concatinators,"tag") -registermethod("locators",locators,"uri") -registermethod("hashers",hashers,"uri") -registermethod("generators",generators,"uri") - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-res"] = package.loaded["data-res"] or true - --- original size: 61799, stripped down to: 42957 - -if not modules then modules={} end modules ['data-res']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch -local concat,insert,sortedkeys=table.concat,table.insert,table.sortedkeys -local next,type,rawget=next,type,rawget -local os=os -local P,S,R,C,Cc,Cs,Ct,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Carg -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local formatters=string.formatters -local filedirname=file.dirname -local filebasename=file.basename -local suffixonly=file.suffixonly -local filejoin=file.join -local collapsepath=file.collapsepath -local joinpath=file.joinpath -local allocate=utilities.storage.allocate -local settings_to_array=utilities.parsers.settings_to_array -local setmetatableindex=table.setmetatableindex -local luasuffixes=utilities.lua.suffixes -local getcurrentdir=lfs.currentdir -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end) -local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end) -local report_resolving=logs.reporter("resolvers","resolving") -local resolvers=resolvers -local expandedpathfromlist=resolvers.expandedpathfromlist -local checkedvariable=resolvers.checkedvariable -local splitconfigurationpath=resolvers.splitconfigurationpath -local methodhandler=resolvers.methodhandler -local initializesetter=utilities.setters.initialize -local ostype,osname,osenv,ossetenv,osgetenv=os.type,os.name,os.env,os.setenv,os.getenv -resolvers.cacheversion='1.0.1' -resolvers.configbanner='' -resolvers.homedir=environment.homedir -resolvers.criticalvars=allocate { "SELFAUTOLOC","SELFAUTODIR","SELFAUTOPARENT","TEXMFCNF","TEXMF","TEXOS" } -resolvers.luacnfname="texmfcnf.lua" -resolvers.luacnfstate="unknown" -if environment.default_texmfcnf then - resolvers.luacnfspec="home:texmf/web2c;"..environment.default_texmfcnf -else - resolvers.luacnfspec=concat ({ - "home:texmf/web2c", - "selfautoparent:/texmf-local/web2c", - "selfautoparent:/texmf-context/web2c", - "selfautoparent:/texmf-dist/web2c", - "selfautoparent:/texmf/web2c", - },";") -end -local unset_variable="unset" -local formats=resolvers.formats -local suffixes=resolvers.suffixes -local dangerous=resolvers.dangerous -local suffixmap=resolvers.suffixmap -resolvers.defaultsuffixes={ "tex" } -resolvers.instance=resolvers.instance or nil -local instance=resolvers.instance or nil -function resolvers.setenv(key,value,raw) - if instance then - instance.environment[key]=value - ossetenv(key,raw and value or resolvers.resolve(value)) - end -end -local function getenv(key) - local value=rawget(instance.environment,key) - if value and value~="" then - return value - else - local e=osgetenv(key) - return e~=nil and e~="" and checkedvariable(e) or "" - end -end -resolvers.getenv=getenv -resolvers.env=getenv -local function resolve(k) - return instance.expansions[k] -end -local dollarstripper=lpeg.stripper("$") -local inhibitstripper=P("!")^0*Cs(P(1)^0) -local backslashswapper=lpeg.replacer("\\","/") -local somevariable=P("$")/"" -local somekey=C(R("az","AZ","09","__","--")^1) -local somethingelse=P(";")*((1-S("!{}/\\"))^1*P(";")/"")+P(";")*(P(";")/"")+P(1) -local variableexpander=Cs((somevariable*(somekey/resolve)+somethingelse)^1 ) -local cleaner=P("\\")/"/"+P(";")*S("!{}/\\")^0*P(";")^1/";" -local variablecleaner=Cs((cleaner+P(1))^0) -local somevariable=R("az","AZ","09","__","--")^1/resolve -local variable=(P("$")/"")*(somevariable+(P("{")/"")*somevariable*(P("}")/"")) -local variableresolver=Cs((variable+P(1))^0) -local function expandedvariable(var) - return lpegmatch(variableexpander,var) or var -end -function resolvers.newinstance() - if trace_locating then - report_resolving("creating instance") - end - local environment,variables,expansions,order=allocate(),allocate(),allocate(),allocate() - local newinstance={ - environment=environment, - variables=variables, - expansions=expansions, - order=order, - files=allocate(), - setups=allocate(), - found=allocate(), - foundintrees=allocate(), - hashes=allocate(), - hashed=allocate(), - specification=allocate(), - lists=allocate(), - data=allocate(), - fakepaths=allocate(), - remember=true, - diskcache=true, - renewcache=false, - renewtree=false, - loaderror=false, - savelists=true, - pattern=nil, - force_suffixes=true, - } - setmetatableindex(variables,function(t,k) - local v - for i=1,#order do - v=order[i][k] - if v~=nil then - t[k]=v - return v - end - end - if v==nil then - v="" - end - t[k]=v - return v - end) - setmetatableindex(environment,function(t,k) - local v=osgetenv(k) - if v==nil then - v=variables[k] - end - if v~=nil then - v=checkedvariable(v) or "" - end - v=resolvers.repath(v) - t[k]=v - return v - end) - setmetatableindex(expansions,function(t,k) - local v=environment[k] - if type(v)=="string" then - v=lpegmatch(variableresolver,v) - v=lpegmatch(variablecleaner,v) - end - t[k]=v - return v - end) - return newinstance -end -function resolvers.setinstance(someinstance) - instance=someinstance - resolvers.instance=someinstance - return someinstance -end -function resolvers.reset() - return resolvers.setinstance(resolvers.newinstance()) -end -local function reset_hashes() - instance.lists={} - instance.found={} -end -local slash=P("/") -local pathexpressionpattern=Cs ( - Cc("^")*( - Cc("%")*S(".-")+slash^2*P(-1)/"/.*" -+slash^2/"/"+(1-slash)*P(-1)*Cc("/")+P(1) - )^1*Cc("$") -) -local cache={} -local function makepathexpression(str) - if str=="." then - return "^%./$" - else - local c=cache[str] - if not c then - c=lpegmatch(pathexpressionpattern,str) - cache[str]=c - end - return c - end -end -local function reportcriticalvariables(cnfspec) - if trace_locating then - for i=1,#resolvers.criticalvars do - local k=resolvers.criticalvars[i] - local v=resolvers.getenv(k) or "unknown" - report_resolving("variable %a set to %a",k,v) - end - report_resolving() - if cnfspec then - report_resolving("using configuration specification %a",type(cnfspec)=="table" and concat(cnfspec,",") or cnfspec) - end - report_resolving() - end - reportcriticalvariables=function() end -end -local function identify_configuration_files() - local specification=instance.specification - if #specification==0 then - local cnfspec=getenv("TEXMFCNF") - if cnfspec=="" then - cnfspec=resolvers.luacnfspec - resolvers.luacnfstate="default" - else - resolvers.luacnfstate="environment" - end - reportcriticalvariables(cnfspec) - local cnfpaths=expandedpathfromlist(resolvers.splitpath(cnfspec)) - local luacnfname=resolvers.luacnfname - for i=1,#cnfpaths do - local filepath=cnfpaths[i] - local filename=collapsepath(filejoin(filepath,luacnfname)) - local realname=resolvers.resolve(filename) - if trace_locating then - local fullpath=gsub(resolvers.resolve(collapsepath(filepath)),"//","/") - local weirdpath=find(fullpath,"/texmf.+/texmf") or not find(fullpath,"/web2c") - report_resolving("looking for %a on %s path %a from specification %a",luacnfname,weirdpath and "weird" or "given",fullpath,filepath) - end - if lfs.isfile(realname) then - specification[#specification+1]=filename - if trace_locating then - report_resolving("found configuration file %a",realname) - end - end - end - if trace_locating then - report_resolving() - end - elseif trace_locating then - report_resolving("configuration files already identified") - end -end -local function load_configuration_files() - local specification=instance.specification - if #specification>0 then - local luacnfname=resolvers.luacnfname - for i=1,#specification do - local filename=specification[i] - local pathname=filedirname(filename) - local filename=filejoin(pathname,luacnfname) - local realname=resolvers.resolve(filename) - local blob=loadfile(realname) - if blob then - local setups=instance.setups - local data=blob() - local parent=data and data.parent - if parent then - local filename=filejoin(pathname,parent) - local realname=resolvers.resolve(filename) - local blob=loadfile(realname) - if blob then - local parentdata=blob() - if parentdata then - report_resolving("loading configuration file %a",filename) - data=table.merged(parentdata,data) - end - end - end - data=data and data.content - if data then - if trace_locating then - report_resolving("loading configuration file %a",filename) - report_resolving() - end - local variables=data.variables or {} - local warning=false - for k,v in next,data do - local variant=type(v) - if variant=="table" then - initializesetter(filename,k,v) - elseif variables[k]==nil then - if trace_locating and not warning then - report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable", - k,resolvers.resolve(filename)) - warning=true - end - variables[k]=v - end - end - setups[pathname]=variables - if resolvers.luacnfstate=="default" then - local cnfspec=variables["TEXMFCNF"] - if cnfspec then - if trace_locating then - report_resolving("reloading configuration due to TEXMF redefinition") - end - resolvers.setenv("TEXMFCNF",cnfspec) - instance.specification={} - identify_configuration_files() - load_configuration_files() - resolvers.luacnfstate="configuration" - break - end - end - else - if trace_locating then - report_resolving("skipping configuration file %a (no content)",filename) - end - setups[pathname]={} - instance.loaderror=true - end - elseif trace_locating then - report_resolving("skipping configuration file %a (no valid format)",filename) - end - instance.order[#instance.order+1]=instance.setups[pathname] - if instance.loaderror then - break - end - end - elseif trace_locating then - report_resolving("warning: no lua configuration files found") - end -end -local function load_file_databases() - instance.loaderror,instance.files=false,allocate() - if not instance.renewcache then - local hashes=instance.hashes - for k=1,#hashes do - local hash=hashes[k] - resolvers.hashers.byscheme(hash.type,hash.name) - if instance.loaderror then break end - end - end -end -local function locate_file_databases() - local texmfpaths=resolvers.expandedpathlist("TEXMF") - if #texmfpaths>0 then - for i=1,#texmfpaths do - local path=collapsepath(texmfpaths[i]) - path=gsub(path,"/+$","") - local stripped=lpegmatch(inhibitstripper,path) - if stripped~="" then - local runtime=stripped==path - path=resolvers.cleanpath(path) - local spec=resolvers.splitmethod(stripped) - if runtime and (spec.noscheme or spec.scheme=="file") then - stripped="tree:///"..stripped - elseif spec.scheme=="cache" or spec.scheme=="file" then - stripped=spec.path - end - if trace_locating then - if runtime then - report_resolving("locating list of %a (runtime) (%s)",path,stripped) - else - report_resolving("locating list of %a (cached)",path) - end - end - methodhandler('locators',stripped) - end - end - if trace_locating then - report_resolving() - end - elseif trace_locating then - report_resolving("no texmf paths are defined (using TEXMF)") - end -end -local function generate_file_databases() - local hashes=instance.hashes - for k=1,#hashes do - local hash=hashes[k] - methodhandler('generators',hash.name) - end - if trace_locating then - report_resolving() - end -end -local function save_file_databases() - for i=1,#instance.hashes do - local hash=instance.hashes[i] - local cachename=hash.name - if hash.cache then - local content=instance.files[cachename] - caches.collapsecontent(content) - if trace_locating then - report_resolving("saving tree %a",cachename) - end - caches.savecontent(cachename,"files",content) - elseif trace_locating then - report_resolving("not saving runtime tree %a",cachename) - end - end -end -function resolvers.renew(hashname) - if hashname and hashname~="" then - local expanded=resolvers.expansion(hashname) or "" - if expanded~="" then - if trace_locating then - report_resolving("identifying tree %a from %a",expanded,hashname) - end - hashname=expanded - else - if trace_locating then - report_resolving("identifying tree %a",hashname) - end - end - local realpath=resolvers.resolve(hashname) - if lfs.isdir(realpath) then - if trace_locating then - report_resolving("using path %a",realpath) - end - methodhandler('generators',hashname) - local content=instance.files[hashname] - caches.collapsecontent(content) - if trace_locating then - report_resolving("saving tree %a",hashname) - end - caches.savecontent(hashname,"files",content) - else - report_resolving("invalid path %a",realpath) - end - end -end -local function load_databases() - locate_file_databases() - if instance.diskcache and not instance.renewcache then - load_file_databases() - if instance.loaderror then - generate_file_databases() - save_file_databases() - end - else - generate_file_databases() - if instance.renewcache then - save_file_databases() - end - end -end -function resolvers.appendhash(type,name,cache) - if not instance.hashed[name] then - if trace_locating then - report_resolving("hash %a appended",name) - end - insert(instance.hashes,{ type=type,name=name,cache=cache } ) - instance.hashed[name]=cache - end -end -function resolvers.prependhash(type,name,cache) - if not instance.hashed[name] then - if trace_locating then - report_resolving("hash %a prepended",name) - end - insert(instance.hashes,1,{ type=type,name=name,cache=cache } ) - instance.hashed[name]=cache - end -end -function resolvers.extendtexmfvariable(specification) - local t=resolvers.splitpath(getenv("TEXMF")) - insert(t,1,specification) - local newspec=concat(t,",") - if instance.environment["TEXMF"] then - instance.environment["TEXMF"]=newspec - elseif instance.variables["TEXMF"] then - instance.variables["TEXMF"]=newspec - else - end - reset_hashes() -end -function resolvers.splitexpansions() - local ie=instance.expansions - for k,v in next,ie do - local t,tn,h,p={},0,{},splitconfigurationpath(v) - for kk=1,#p do - local vv=p[kk] - if vv~="" and not h[vv] then - tn=tn+1 - t[tn]=vv - h[vv]=true - end - end - if #t>1 then - ie[k]=t - else - ie[k]=t[1] - end - end -end -function resolvers.datastate() - return caches.contentstate() -end -function resolvers.variable(name) - local name=name and lpegmatch(dollarstripper,name) - local result=name and instance.variables[name] - return result~=nil and result or "" -end -function resolvers.expansion(name) - local name=name and lpegmatch(dollarstripper,name) - local result=name and instance.expansions[name] - return result~=nil and result or "" -end -function resolvers.unexpandedpathlist(str) - local pth=resolvers.variable(str) - local lst=resolvers.splitpath(pth) - return expandedpathfromlist(lst) -end -function resolvers.unexpandedpath(str) - return joinpath(resolvers.unexpandedpathlist(str)) -end -local done={} -function resolvers.resetextrapath() - local ep=instance.extra_paths - if not ep then - ep,done={},{} - instance.extra_paths=ep - elseif #ep>0 then - instance.lists,done={},{} - end -end -function resolvers.registerextrapath(paths,subpaths) - paths=settings_to_array(paths) - subpaths=settings_to_array(subpaths) - local ep=instance.extra_paths or {} - local oldn=#ep - local newn=oldn - local nofpaths=#paths - local nofsubpaths=#subpaths - if nofpaths>0 then - if nofsubpaths>0 then - for i=1,nofpaths do - local p=paths[i] - for j=1,nofsubpaths do - local s=subpaths[j] - local ps=p.."/"..s - if not done[ps] then - newn=newn+1 - ep[newn]=resolvers.cleanpath(ps) - done[ps]=true - end - end - end - else - for i=1,nofpaths do - local p=paths[i] - if not done[p] then - newn=newn+1 - ep[newn]=resolvers.cleanpath(p) - done[p]=true - end - end - end - elseif nofsubpaths>0 then - for i=1,oldn do - for j=1,nofsubpaths do - local s=subpaths[j] - local ps=ep[i].."/"..s - if not done[ps] then - newn=newn+1 - ep[newn]=resolvers.cleanpath(ps) - done[ps]=true - end - end - end - end - if newn>0 then - instance.extra_paths=ep - end - if newn>oldn then - instance.lists={} - end -end -local function made_list(instance,list) - local ep=instance.extra_paths - if not ep or #ep==0 then - return list - else - local done,new,newn={},{},0 - for k=1,#list do - local v=list[k] - if not done[v] then - if find(v,"^[%.%/]$") then - done[v]=true - newn=newn+1 - new[newn]=v - else - break - end - end - end - for k=1,#ep do - local v=ep[k] - if not done[v] then - done[v]=true - newn=newn+1 - new[newn]=v - end - end - for k=1,#list do - local v=list[k] - if not done[v] then - done[v]=true - newn=newn+1 - new[newn]=v - end - end - return new - end -end -function resolvers.cleanpathlist(str) - local t=resolvers.expandedpathlist(str) - if t then - for i=1,#t do - t[i]=collapsepath(resolvers.cleanpath(t[i])) - end - end - return t -end -function resolvers.expandpath(str) - return joinpath(resolvers.expandedpathlist(str)) -end -function resolvers.expandedpathlist(str) - if not str then - return {} - elseif instance.savelists then - str=lpegmatch(dollarstripper,str) - local lists=instance.lists - local lst=lists[str] - if not lst then - local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str))) - lst=expandedpathfromlist(l) - lists[str]=lst - end - return lst - else - local lst=resolvers.splitpath(resolvers.expansion(str)) - return made_list(instance,expandedpathfromlist(lst)) - end -end -function resolvers.expandedpathlistfromvariable(str) - str=lpegmatch(dollarstripper,str) - local tmp=resolvers.variableofformatorsuffix(str) - return resolvers.expandedpathlist(tmp~="" and tmp or str) -end -function resolvers.expandpathfromvariable(str) - return joinpath(resolvers.expandedpathlistfromvariable(str)) -end -function resolvers.expandbraces(str) - local ori=str - local pth=expandedpathfromlist(resolvers.splitpath(ori)) - return joinpath(pth) -end -function resolvers.registerfilehash(name,content,someerror) - if content then - instance.files[name]=content - else - instance.files[name]={} - if somerror==true then - instance.loaderror=someerror - end - end -end -local function isreadable(name) - local readable=lfs.isfile(name) - if trace_detail then - if readable then - report_resolving("file %a is readable",name) - else - report_resolving("file %a is not readable",name) - end - end - return readable -end -local function collect_files(names) - local filelist,noffiles={},0 - for k=1,#names do - local fname=names[k] - if trace_detail then - report_resolving("checking name %a",fname) - end - local bname=filebasename(fname) - local dname=filedirname(fname) - if dname=="" or find(dname,"^%.") then - dname=false - else - dname=gsub(dname,"%*",".*") - dname="/"..dname.."$" - end - local hashes=instance.hashes - for h=1,#hashes do - local hash=hashes[h] - local blobpath=hash.name - local files=blobpath and instance.files[blobpath] - if files then - if trace_detail then - report_resolving("deep checking %a, base %a, pattern %a",blobpath,bname,dname) - end - local blobfile=files[bname] - if not blobfile then - local rname="remap:"..bname - blobfile=files[rname] - if blobfile then - bname=files[rname] - blobfile=files[bname] - end - end - if blobfile then - local blobroot=files.__path__ or blobpath - if type(blobfile)=='string' then - if not dname or find(blobfile,dname) then - local variant=hash.type - local search=filejoin(blobroot,blobfile,bname) - local result=methodhandler('concatinators',hash.type,blobroot,blobfile,bname) - if trace_detail then - report_resolving("match: variant %a, search %a, result %a",variant,search,result) - end - noffiles=noffiles+1 - filelist[noffiles]={ variant,search,result } - end - else - for kk=1,#blobfile do - local vv=blobfile[kk] - if not dname or find(vv,dname) then - local variant=hash.type - local search=filejoin(blobroot,vv,bname) - local result=methodhandler('concatinators',hash.type,blobroot,vv,bname) - if trace_detail then - report_resolving("match: variant %a, search %a, result %a",variant,search,result) - end - noffiles=noffiles+1 - filelist[noffiles]={ variant,search,result } - end - end - end - end - elseif trace_locating then - report_resolving("no match in %a (%s)",blobpath,bname) - end - end - end - return noffiles>0 and filelist or nil -end -local fit={} -function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname) - local foundintrees=instance.foundintrees - if usedmethod=="direct" and filename==foundname and fit[foundname] then - else - local t={ - filename=filename, - format=format~="" and format or nil, - filetype=filetype~="" and filetype or nil, - usedmethod=usedmethod, - foundname=foundname, - } - fit[foundname]=t - foundintrees[#foundintrees+1]=t - end -end -local function can_be_dir(name) - local fakepaths=instance.fakepaths - if not fakepaths[name] then - if lfs.isdir(name) then - fakepaths[name]=1 - else - fakepaths[name]=2 - end - end - return fakepaths[name]==1 -end -local preparetreepattern=Cs((P(".")/"%%."+P("-")/"%%-"+P(1))^0*Cc("$")) -local collect_instance_files -local function find_analyze(filename,askedformat,allresults) - local filetype,wantedfiles,ext='',{},suffixonly(filename) - wantedfiles[#wantedfiles+1]=filename - if askedformat=="" then - if ext=="" or not suffixmap[ext] then - local defaultsuffixes=resolvers.defaultsuffixes - for i=1,#defaultsuffixes do - local forcedname=filename..'.'..defaultsuffixes[i] - wantedfiles[#wantedfiles+1]=forcedname - filetype=resolvers.formatofsuffix(forcedname) - if trace_locating then - report_resolving("forcing filetype %a",filetype) - end - end - else - filetype=resolvers.formatofsuffix(filename) - if trace_locating then - report_resolving("using suffix based filetype %a",filetype) - end - end - else - if ext=="" or not suffixmap[ext] then - local format_suffixes=suffixes[askedformat] - if format_suffixes then - for i=1,#format_suffixes do - wantedfiles[#wantedfiles+1]=filename.."."..format_suffixes[i] - end - end - end - filetype=askedformat - if trace_locating then - report_resolving("using given filetype %a",filetype) - end - end - return filetype,wantedfiles -end -local function find_direct(filename,allresults) - if not dangerous[askedformat] and isreadable(filename) then - if trace_detail then - report_resolving("file %a found directly",filename) - end - return "direct",{ filename } - end -end -local function find_wildcard(filename,allresults) - if find(filename,'%*') then - if trace_locating then - report_resolving("checking wildcard %a",filename) - end - local method,result=resolvers.findwildcardfiles(filename) - if result then - return "wildcard",result - end - end -end -local function find_qualified(filename,allresults,askedformat,alsostripped) - if not file.is_qualified_path(filename) then - return - end - if trace_locating then - report_resolving("checking qualified name %a",filename) - end - if isreadable(filename) then - if trace_detail then - report_resolving("qualified file %a found",filename) - end - return "qualified",{ filename } - end - if trace_detail then - report_resolving("locating qualified file %a",filename) - end - local forcedname,suffix="",suffixonly(filename) - if suffix=="" then - local format_suffixes=askedformat=="" and resolvers.defaultsuffixes or suffixes[askedformat] - if format_suffixes then - for i=1,#format_suffixes do - local s=format_suffixes[i] - forcedname=filename.."."..s - if isreadable(forcedname) then - if trace_locating then - report_resolving("no suffix, forcing format filetype %a",s) - end - return "qualified",{ forcedname } - end - end - end - end - if alsostripped and suffix and suffix~="" then - local basename=filebasename(filename) - local pattern=lpegmatch(preparetreepattern,filename) - local savedformat=askedformat - local format=savedformat or "" - if format=="" then - askedformat=resolvers.formatofsuffix(suffix) - end - if not format then - askedformat="othertextfiles" - end - if basename~=filename then - local resolved=collect_instance_files(basename,askedformat,allresults) - if #resolved==0 then - local lowered=lower(basename) - if filename~=lowered then - resolved=collect_instance_files(lowered,askedformat,allresults) - end - end - resolvers.format=savedformat - if #resolved>0 then - local result={} - for r=1,#resolved do - local rr=resolved[r] - if find(rr,pattern) then - result[#result+1]=rr - end - end - if #result>0 then - return "qualified",result - end - end - end - end -end -local function check_subpath(fname) - if isreadable(fname) then - if trace_detail then - report_resolving("found %a by deep scanning",fname) - end - return fname - end -end -local function find_intree(filename,filetype,wantedfiles,allresults) - local typespec=resolvers.variableofformat(filetype) - local pathlist=resolvers.expandedpathlist(typespec) - local method="intree" - if pathlist and #pathlist>0 then - local filelist=collect_files(wantedfiles) - local dirlist={} - if filelist then - for i=1,#filelist do - dirlist[i]=filedirname(filelist[i][3]).."/" - end - end - if trace_detail then - report_resolving("checking filename %a",filename) - end - local resolve=resolvers.resolve - local result={} - for k=1,#pathlist do - local path=pathlist[k] - local pathname=lpegmatch(inhibitstripper,path) - local doscan=path==pathname - if not find (pathname,'//$') then - doscan=false - end - local done=false - if filelist then - local expression=makepathexpression(pathname) - if trace_detail then - report_resolving("using pattern %a for path %a",expression,pathname) - end - for k=1,#filelist do - local fl=filelist[k] - local f=fl[2] - local d=dirlist[k] - if find(d,expression) or find(resolve(d),expression) then - result[#result+1]=resolve(fl[3]) - done=true - if allresults then - if trace_detail then - report_resolving("match to %a in hash for file %a and path %a, continue scanning",expression,f,d) - end - else - if trace_detail then - report_resolving("match to %a in hash for file %a and path %a, quit scanning",expression,f,d) - end - break - end - elseif trace_detail then - report_resolving("no match to %a in hash for file %a and path %a",expression,f,d) - end - end - end - if done then - method="database" - else - method="filesystem" - pathname=gsub(pathname,"/+$","") - pathname=resolve(pathname) - local scheme=url.hasscheme(pathname) - if not scheme or scheme=="file" then - local pname=gsub(pathname,"%.%*$",'') - if not find(pname,"%*") then - if can_be_dir(pname) then - for k=1,#wantedfiles do - local w=wantedfiles[k] - local fname=check_subpath(filejoin(pname,w)) - if fname then - result[#result+1]=fname - done=true - if not allresults then - break - end - end - end - if not done and doscan then - local files=resolvers.simplescanfiles(pname,false,true) - for k=1,#wantedfiles do - local w=wantedfiles[k] - local subpath=files[w] - if not subpath or subpath=="" then - elseif type(subpath)=="string" then - local fname=check_subpath(filejoin(pname,subpath,w)) - if fname then - result[#result+1]=fname - done=true - if not allresults then - break - end - end - else - for i=1,#subpath do - local sp=subpath[i] - if sp=="" then - else - local fname=check_subpath(filejoin(pname,sp,w)) - if fname then - result[#result+1]=fname - done=true - if not allresults then - break - end - end - end - end - if done and not allresults then - break - end - end - end - end - end - else - end - end - end - if done and not allresults then - break - end - end - if #result>0 then - return method,result - end - end -end -local function find_onpath(filename,filetype,wantedfiles,allresults) - if trace_detail then - report_resolving("checking filename %a, filetype %a, wanted files %a",filename,filetype,concat(wantedfiles," | ")) - end - local result={} - for k=1,#wantedfiles do - local fname=wantedfiles[k] - if fname and isreadable(fname) then - filename=fname - result[#result+1]=filejoin('.',fname) - if not allresults then - break - end - end - end - if #result>0 then - return "onpath",result - end -end -local function find_otherwise(filename,filetype,wantedfiles,allresults) - local filelist=collect_files(wantedfiles) - local fl=filelist and filelist[1] - if fl then - return "otherwise",{ resolvers.resolve(fl[3]) } - end -end -collect_instance_files=function(filename,askedformat,allresults) - askedformat=askedformat or "" - filename=collapsepath(filename,".") - filename=gsub(filename,"^%./",getcurrentdir().."/") - if allresults then - local filetype,wantedfiles=find_analyze(filename,askedformat) - local results={ - { find_direct (filename,true) }, - { find_wildcard (filename,true) }, - { find_qualified(filename,true,askedformat) }, - { find_intree (filename,filetype,wantedfiles,true) }, - { find_onpath (filename,filetype,wantedfiles,true) }, - { find_otherwise(filename,filetype,wantedfiles,true) }, - } - local result,status,done={},{},{} - for k,r in next,results do - local method,list=r[1],r[2] - if method and list then - for i=1,#list do - local c=collapsepath(list[i]) - if not done[c] then - result[#result+1]=c - done[c]=true - end - status[#status+1]=formatters["%-10s: %s"](method,c) - end - end - end - if trace_detail then - report_resolving("lookup status: %s",table.serialize(status,filename)) - end - return result,status - else - local method,result,stamp,filetype,wantedfiles - if instance.remember then - stamp=formatters["%s--%s"](filename,askedformat) - result=stamp and instance.found[stamp] - if result then - if trace_locating then - report_resolving("remembered file %a",filename) - end - return result - end - end - method,result=find_direct(filename) - if not result then - method,result=find_wildcard(filename) - if not result then - method,result=find_qualified(filename,false,askedformat) - if not result then - filetype,wantedfiles=find_analyze(filename,askedformat) - method,result=find_intree(filename,filetype,wantedfiles) - if not result then - method,result=find_onpath(filename,filetype,wantedfiles) - if not result then - method,result=find_otherwise(filename,filetype,wantedfiles) - end - end - end - end - end - if result and #result>0 then - local foundname=collapsepath(result[1]) - resolvers.registerintrees(filename,askedformat,filetype,method,foundname) - result={ foundname } - else - result={} - end - if stamp then - if trace_locating then - report_resolving("remembering file %a",filename) - end - instance.found[stamp]=result - end - return result - end -end -local function findfiles(filename,filetype,allresults) - local result,status=collect_instance_files(filename,filetype or "",allresults) - if not result or #result==0 then - local lowered=lower(filename) - if filename~=lowered then - result,status=collect_instance_files(lowered,filetype or "",allresults) - end - end - return result or {},status -end -function resolvers.findfiles(filename,filetype) - return findfiles(filename,filetype,true) -end -function resolvers.findfile(filename,filetype) - return findfiles(filename,filetype,false)[1] or "" -end -function resolvers.findpath(filename,filetype) - return filedirname(findfiles(filename,filetype,false)[1] or "") -end -local function findgivenfiles(filename,allresults) - local bname,result=filebasename(filename),{} - local hashes=instance.hashes - local noffound=0 - for k=1,#hashes do - local hash=hashes[k] - local files=instance.files[hash.name] or {} - local blist=files[bname] - if not blist then - local rname="remap:"..bname - blist=files[rname] - if blist then - bname=files[rname] - blist=files[bname] - end - end - if blist then - if type(blist)=='string' then - local found=methodhandler('concatinators',hash.type,hash.name,blist,bname) or "" - if found~="" then - noffound=noffound+1 - result[noffound]=resolvers.resolve(found) - if not allresults then - break - end - end - else - for kk=1,#blist do - local vv=blist[kk] - local found=methodhandler('concatinators',hash.type,hash.name,vv,bname) or "" - if found~="" then - noffound=noffound+1 - result[noffound]=resolvers.resolve(found) - if not allresults then break end - end - end - end - end - end - return result -end -function resolvers.findgivenfiles(filename) - return findgivenfiles(filename,true) -end -function resolvers.findgivenfile(filename) - return findgivenfiles(filename,false)[1] or "" -end -local function doit(path,blist,bname,tag,variant,result,allresults) - local done=false - if blist and variant then - local resolve=resolvers.resolve - if type(blist)=='string' then - if find(lower(blist),path) then - local full=methodhandler('concatinators',variant,tag,blist,bname) or "" - result[#result+1]=resolve(full) - done=true - end - else - for kk=1,#blist do - local vv=blist[kk] - if find(lower(vv),path) then - local full=methodhandler('concatinators',variant,tag,vv,bname) or "" - result[#result+1]=resolve(full) - done=true - if not allresults then break end - end - end - end - end - return done -end -local makewildcard=Cs( - (P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0 -) -function resolvers.wildcardpattern(pattern) - return lpegmatch(makewildcard,pattern) or pattern -end -local function findwildcardfiles(filename,allresults,result) - result=result or {} - local base=filebasename(filename) - local dirn=filedirname(filename) - local path=lower(lpegmatch(makewildcard,dirn) or dirn) - local name=lower(lpegmatch(makewildcard,base) or base) - local files,done=instance.files,false - if find(name,"%*") then - local hashes=instance.hashes - for k=1,#hashes do - local hash=hashes[k] - local hashname,hashtype=hash.name,hash.type - for kk,hh in next,files[hashname] do - if not find(kk,"^remap:") then - if find(lower(kk),name) then - if doit(path,hh,kk,hashname,hashtype,result,allresults) then done=true end - if done and not allresults then break end - end - end - end - end - else - local hashes=instance.hashes - for k=1,#hashes do - local hash=hashes[k] - local hashname,hashtype=hash.name,hash.type - if doit(path,files[hashname][base],base,hashname,hashtype,result,allresults) then done=true end - if done and not allresults then break end - end - end - return result -end -function resolvers.findwildcardfiles(filename,result) - return findwildcardfiles(filename,true,result) -end -function resolvers.findwildcardfile(filename) - return findwildcardfiles(filename,false)[1] or "" -end -function resolvers.automount() -end -function resolvers.load(option) - statistics.starttiming(instance) - identify_configuration_files() - load_configuration_files() - if option~="nofiles" then - load_databases() - resolvers.automount() - end - statistics.stoptiming(instance) - local files=instance.files - return files and next(files) and true -end -function resolvers.loadtime() - return statistics.elapsedtime(instance) -end -local function report(str) - if trace_locating then - report_resolving(str) - else - print(str) - end -end -function resolvers.dowithfilesandreport(command,files,...) - if files and #files>0 then - if trace_locating then - report('') - end - if type(files)=="string" then - files={ files } - end - for f=1,#files do - local file=files[f] - local result=command(file,...) - if type(result)=='string' then - report(result) - else - for i=1,#result do - report(result[i]) - end - end - end - end -end -function resolvers.showpath(str) - return joinpath(resolvers.expandedpathlist(resolvers.formatofvariable(str))) -end -function resolvers.registerfile(files,name,path) - if files[name] then - if type(files[name])=='string' then - files[name]={ files[name],path } - else - files[name]=path - end - else - files[name]=path - end -end -function resolvers.dowithpath(name,func) - local pathlist=resolvers.expandedpathlist(name) - for i=1,#pathlist do - func("^"..resolvers.cleanpath(pathlist[i])) - end -end -function resolvers.dowithvariable(name,func) - func(expandedvariable(name)) -end -function resolvers.locateformat(name) - local engine=environment.ownmain or "luatex" - local barename=file.removesuffix(name) - local fullname=file.addsuffix(barename,"fmt") - local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or "" - if fmtname=="" then - fmtname=resolvers.findfile(fullname) - fmtname=resolvers.cleanpath(fmtname) - end - if fmtname~="" then - local barename=file.removesuffix(fmtname) - local luaname=file.addsuffix(barename,luasuffixes.lua) - local lucname=file.addsuffix(barename,luasuffixes.luc) - local luiname=file.addsuffix(barename,luasuffixes.lui) - if lfs.isfile(luiname) then - return barename,luiname - elseif lfs.isfile(lucname) then - return barename,lucname - elseif lfs.isfile(luaname) then - return barename,luaname - end - end - return nil,nil -end -function resolvers.booleanvariable(str,default) - local b=resolvers.expansion(str) - if b=="" then - return default - else - b=toboolean(b) - return (b==nil and default) or b - end -end -function resolvers.dowithfilesintree(pattern,handle,before,after) - local instance=resolvers.instance - local hashes=instance.hashes - for i=1,#hashes do - local hash=hashes[i] - local blobtype=hash.type - local blobpath=hash.name - if blobpath then - if before then - before(blobtype,blobpath,pattern) - end - local files=instance.files[blobpath] - local total,checked,done=0,0,0 - if files then - for k,v in table.sortedhash(files) do - total=total+1 - if find(k,"^remap:") then - elseif find(k,pattern) then - if type(v)=="string" then - checked=checked+1 - if handle(blobtype,blobpath,v,k) then - done=done+1 - end - else - checked=checked+#v - for i=1,#v do - if handle(blobtype,blobpath,v[i],k) then - done=done+1 - end - end - end - end - end - end - if after then - after(blobtype,blobpath,pattern,total,checked,done) - end - end - end -end -resolvers.obsolete=resolvers.obsolete or {} -local obsolete=resolvers.obsolete -resolvers.find_file=resolvers.findfile obsolete.find_file=resolvers.findfile -resolvers.find_files=resolvers.findfiles obsolete.find_files=resolvers.findfiles - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-pre"] = package.loaded["data-pre"] or true - --- original size: 6643, stripped down to: 4401 - -if not modules then modules={} end modules ['data-pre']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local resolvers=resolvers -local prefixes=utilities.storage.allocate() -resolvers.prefixes=prefixes -local cleanpath,findgivenfile,expansion=resolvers.cleanpath,resolvers.findgivenfile,resolvers.expansion -local getenv=resolvers.getenv -local P,S,R,C,Cs,Cc,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.match -local joinpath,basename,dirname=file.join,file.basename,file.dirname -local getmetatable,rawset,type=getmetatable,rawset,type -prefixes.environment=function(str) - return cleanpath(expansion(str)) -end -prefixes.relative=function(str,n) - if io.exists(str) then - elseif io.exists("./"..str) then - str="./"..str - else - local p="../" - for i=1,n or 2 do - if io.exists(p..str) then - str=p..str - break - else - p=p.."../" - end - end - end - return cleanpath(str) -end -prefixes.auto=function(str) - local fullname=prefixes.relative(str) - if not lfs.isfile(fullname) then - fullname=prefixes.locate(str) - end - return fullname -end -prefixes.locate=function(str) - local fullname=findgivenfile(str) or "" - return cleanpath((fullname~="" and fullname) or str) -end -prefixes.filename=function(str) - local fullname=findgivenfile(str) or "" - return cleanpath(basename((fullname~="" and fullname) or str)) -end -prefixes.pathname=function(str) - local fullname=findgivenfile(str) or "" - return cleanpath(dirname((fullname~="" and fullname) or str)) -end -prefixes.selfautoloc=function(str) - return cleanpath(joinpath(getenv('SELFAUTOLOC'),str)) -end -prefixes.selfautoparent=function(str) - return cleanpath(joinpath(getenv('SELFAUTOPARENT'),str)) -end -prefixes.selfautodir=function(str) - return cleanpath(joinpath(getenv('SELFAUTODIR'),str)) -end -prefixes.home=function(str) - return cleanpath(joinpath(getenv('HOME'),str)) -end -local function toppath() - local inputstack=resolvers.inputstack - if not inputstack then - return "." - end - local pathname=dirname(inputstack[#inputstack] or "") - if pathname=="" then - return "." - else - return pathname - end -end -resolvers.toppath=toppath -prefixes.toppath=function(str) - return cleanpath(joinpath(toppath(),str)) -end -prefixes.env=prefixes.environment -prefixes.rel=prefixes.relative -prefixes.loc=prefixes.locate -prefixes.kpse=prefixes.locate -prefixes.full=prefixes.locate -prefixes.file=prefixes.filename -prefixes.path=prefixes.pathname -function resolvers.allprefixes(separator) - local all=table.sortedkeys(prefixes) - if separator then - for i=1,#all do - all[i]=all[i]..":" - end - end - return all -end -local function _resolve_(method,target) - local action=prefixes[method] - if action then - return action(target) - else - return method..":"..target - end -end -local resolved,abstract={},{} -function resolvers.resetresolve(str) - resolved,abstract={},{} -end -local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0) -local prefix=C(R("az")^2)*P(":") -local target=C((1-S(" \"\';,"))^1) -local notarget=(#S(";,")+P(-1))*Cc("") -local pattern=Cs(((prefix*(target+notarget))/_resolve_+P(1))^0) -local function resolve(str) - if type(str)=="table" then - local t={} - for i=1,#str do - t[i]=resolve(str[i]) - end - return t - else - local res=resolved[str] - if not res then - res=lpegmatch(pattern,str) - resolved[str]=res - abstract[res]=str - end - return res - end -end -local function unresolve(str) - return abstract[str] or str -end -resolvers.resolve=resolve -resolvers.unresolve=unresolve -if type(os.uname)=="function" then - for k,v in next,os.uname() do - if not prefixes[k] then - prefixes[k]=function() return v end - end - end -end -if os.type=="unix" then - local pattern - local function makepattern(t,k,v) - if t then - rawset(t,k,v) - end - local colon=P(":") - for k,v in table.sortedpairs(prefixes) do - if p then - p=P(k)+p - else - p=P(k) - end - end - pattern=Cs((p*colon+colon/";"+P(1))^0) - end - makepattern() - getmetatable(prefixes).__newindex=makepattern - function resolvers.repath(str) - return lpegmatch(pattern,str) - end -else - function resolvers.repath(str) - return str - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-inp"] = package.loaded["data-inp"] or true - --- original size: 910, stripped down to: 823 - -if not modules then modules={} end modules ['data-inp']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local allocate=utilities.storage.allocate -local resolvers=resolvers -local methodhandler=resolvers.methodhandler -local registermethod=resolvers.registermethod -local finders=allocate { helpers={},notfound=function() end } -local openers=allocate { helpers={},notfound=function() end } -local loaders=allocate { helpers={},notfound=function() return false,nil,0 end } -registermethod("finders",finders,"uri") -registermethod("openers",openers,"uri") -registermethod("loaders",loaders,"uri") -resolvers.finders=finders -resolvers.openers=openers -resolvers.loaders=loaders - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-out"] = package.loaded["data-out"] or true - --- original size: 530, stripped down to: 475 - -if not modules then modules={} end modules ['data-out']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local allocate=utilities.storage.allocate -local resolvers=resolvers -local registermethod=resolvers.registermethod -local savers=allocate { helpers={} } -resolvers.savers=savers -registermethod("savers",savers,"uri") - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-fil"] = package.loaded["data-fil"] or true - --- original size: 3801, stripped down to: 3231 - -if not modules then modules={} end modules ['data-fil']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local report_files=logs.reporter("resolvers","files") -local resolvers=resolvers -local finders,openers,loaders,savers=resolvers.finders,resolvers.openers,resolvers.loaders,resolvers.savers -local locators,hashers,generators,concatinators=resolvers.locators,resolvers.hashers,resolvers.generators,resolvers.concatinators -local checkgarbage=utilities.garbagecollector and utilities.garbagecollector.check -function locators.file(specification) - local name=specification.filename - local realname=resolvers.resolve(name) - if realname and realname~='' and lfs.isdir(realname) then - if trace_locating then - report_files("file locator %a found as %a",name,realname) - end - resolvers.appendhash('file',name,true) - elseif trace_locating then - report_files("file locator %a not found",name) - end -end -function hashers.file(specification) - local name=specification.filename - local content=caches.loadcontent(name,'files') - resolvers.registerfilehash(name,content,content==nil) -end -function generators.file(specification) - local path=specification.filename - local content=resolvers.scanfiles(path,false,true) - resolvers.registerfilehash(path,content,true) -end -concatinators.file=file.join -function finders.file(specification,filetype) - local filename=specification.filename - local foundname=resolvers.findfile(filename,filetype) - if foundname and foundname~="" then - if trace_locating then - report_files("file finder: %a found",filename) - end - return foundname - else - if trace_locating then - report_files("file finder: %a not found",filename) - end - return finders.notfound() - end -end -function openers.helpers.textopener(tag,filename,f) - return { - reader=function() return f:read () end, - close=function() logs.show_close(filename) return f:close() end, - } -end -function openers.file(specification,filetype) - local filename=specification.filename - if filename and filename~="" then - local f=io.open(filename,"r") - if f then - if trace_locating then - report_files("file opener: %a opened",filename) - end - return openers.helpers.textopener("file",filename,f) - end - end - if trace_locating then - report_files("file opener: %a not found",filename) - end - return openers.notfound() -end -function loaders.file(specification,filetype) - local filename=specification.filename - if filename and filename~="" then - local f=io.open(filename,"rb") - if f then - logs.show_load(filename) - if trace_locating then - report_files("file loader: %a loaded",filename) - end - local s=f:read("*a") - if checkgarbage then - checkgarbage(#s) - end - f:close() - if s then - return true,s,#s - end - end - end - if trace_locating then - report_files("file loader: %a not found",filename) - end - return loaders.notfound() -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-con"] = package.loaded["data-con"] or true - --- original size: 5010, stripped down to: 3588 - -if not modules then modules={} end modules ['data-con']={ - version=1.100, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,lower,gsub=string.format,string.lower,string.gsub -local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end) -local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end) -local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end) -containers=containers or {} -local containers=containers -containers.usecache=true -local report_containers=logs.reporter("resolvers","containers") -local allocated={} -local mt={ - __index=function(t,k) - if k=="writable" then - local writable=caches.getwritablepath(t.category,t.subcategory) or { "." } - t.writable=writable - return writable - elseif k=="readables" then - local readables=caches.getreadablepaths(t.category,t.subcategory) or { "." } - t.readables=readables - return readables - end - end, - __storage__=true -} -function containers.define(category,subcategory,version,enabled) - if category and subcategory then - local c=allocated[category] - if not c then - c={} - allocated[category]=c - end - local s=c[subcategory] - if not s then - s={ - category=category, - subcategory=subcategory, - storage={}, - enabled=enabled, - version=version or math.pi, - trace=false, - } - setmetatable(s,mt) - c[subcategory]=s - end - return s - end -end -function containers.is_usable(container,name) - return container.enabled and caches and caches.is_writable(container.writable,name) -end -function containers.is_valid(container,name) - if name and name~="" then - local storage=container.storage[name] - return storage and storage.cache_version==container.version - else - return false - end -end -function containers.read(container,name) - local storage=container.storage - local stored=storage[name] - if not stored and container.enabled and caches and containers.usecache then - stored=caches.loaddata(container.readables,name) - if stored and stored.cache_version==container.version then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","load",container.subcategory,name) - end - else - stored=nil - end - storage[name]=stored - elseif stored then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","reuse",container.subcategory,name) - end - end - return stored -end -function containers.write(container,name,data) - if data then - data.cache_version=container.version - if container.enabled and caches then - local unique,shared=data.unique,data.shared - data.unique,data.shared=nil,nil - caches.savedata(container.writable,name,data) - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","save",container.subcategory,name) - end - data.unique,data.shared=unique,shared - end - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","store",container.subcategory,name) - end - container.storage[name]=data - end - return data -end -function containers.content(container,name) - return container.storage[name] -end -function containers.cleanname(name) - return (gsub(lower(name),"[^%w\128-\255]+","-")) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-use"] = package.loaded["data-use"] or true - --- original size: 3899, stripped down to: 2984 - -if not modules then modules={} end modules ['data-use']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,lower,gsub,find=string.format,string.lower,string.gsub,string.find -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local report_mounts=logs.reporter("resolvers","mounts") -local resolvers=resolvers -resolvers.automounted=resolvers.automounted or {} -function resolvers.automount(usecache) - local mountpaths=resolvers.cleanpathlist(resolvers.expansion('TEXMFMOUNT')) - if (not mountpaths or #mountpaths==0) and usecache then - mountpaths=caches.getreadablepaths("mount") - end - if mountpaths and #mountpaths>0 then - statistics.starttiming(resolvers.instance) - for k=1,#mountpaths do - local root=mountpaths[k] - local f=io.open(root.."/url.tmi") - if f then - for line in f:lines() do - if line then - if find(line,"^[%%#%-]") then - elseif find(line,"^zip://") then - if trace_locating then - report_mounts("mounting %a",line) - end - table.insert(resolvers.automounted,line) - resolvers.usezipfile(line) - end - end - end - f:close() - end - end - statistics.stoptiming(resolvers.instance) - end -end -statistics.register("used config file",function() return caches.configfiles() end) -statistics.register("used cache path",function() return caches.usedpaths() end) -function statistics.savefmtstatus(texname,formatbanner,sourcefile) - local enginebanner=status.banner - if formatbanner and enginebanner and sourcefile then - local luvname=file.replacesuffix(texname,"luv") - local luvdata={ - enginebanner=enginebanner, - formatbanner=formatbanner, - sourcehash=md5.hex(io.loaddata(resolvers.findfile(sourcefile)) or "unknown"), - sourcefile=sourcefile, - } - io.savedata(luvname,table.serialize(luvdata,true)) - end -end -function statistics.checkfmtstatus(texname) - local enginebanner=status.banner - if enginebanner and texname then - local luvname=file.replacesuffix(texname,"luv") - if lfs.isfile(luvname) then - local luv=dofile(luvname) - if luv and luv.sourcefile then - local sourcehash=md5.hex(io.loaddata(resolvers.findfile(luv.sourcefile)) or "unknown") - local luvbanner=luv.enginebanner or "?" - if luvbanner~=enginebanner then - return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner) - end - local luvhash=luv.sourcehash or "?" - if luvhash~=sourcehash then - return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash) - end - else - return "invalid status file" - end - else - return "missing status file" - end - end - return true -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-zip"] = package.loaded["data-zip"] or true - --- original size: 8489, stripped down to: 6757 - -if not modules then modules={} end modules ['data-zip']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format,find,match=string.format,string.find,string.match -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local report_zip=logs.reporter("resolvers","zip") -local resolvers=resolvers -zip=zip or {} -local zip=zip -zip.archives=zip.archives or {} -local archives=zip.archives -zip.registeredfiles=zip.registeredfiles or {} -local registeredfiles=zip.registeredfiles -local limited=false -directives.register("system.inputmode",function(v) - if not limited then - local i_limiter=io.i_limiter(v) - if i_limiter then - zip.open=i_limiter.protect(zip.open) - limited=true - end - end -end) -local function validzip(str) - if not find(str,"^zip://") then - return "zip:///"..str - else - return str - end -end -function zip.openarchive(name) - if not name or name=="" then - return nil - else - local arch=archives[name] - if not arch then - local full=resolvers.findfile(name) or "" - arch=(full~="" and zip.open(full)) or false - archives[name]=arch - end - return arch - end -end -function zip.closearchive(name) - if not name or (name=="" and archives[name]) then - zip.close(archives[name]) - archives[name]=nil - end -end -function resolvers.locators.zip(specification) - local archive=specification.filename - local zipfile=archive and archive~="" and zip.openarchive(archive) - if trace_locating then - if zipfile then - report_zip("locator: archive %a found",archive) - else - report_zip("locator: archive %a not found",archive) - end - end -end -function resolvers.hashers.zip(specification) - local archive=specification.filename - if trace_locating then - report_zip("loading file %a",archive) - end - resolvers.usezipfile(specification.original) -end -function resolvers.concatinators.zip(zipfile,path,name) - if not path or path=="" then - return format('%s?name=%s',zipfile,name) - else - return format('%s?name=%s/%s',zipfile,path,name) - end -end -function resolvers.finders.zip(specification) - local original=specification.original - local archive=specification.filename - if archive then - local query=url.query(specification.query) - local queryname=query.name - if queryname then - local zfile=zip.openarchive(archive) - if zfile then - if trace_locating then - report_zip("finder: archive %a found",archive) - end - local dfile=zfile:open(queryname) - if dfile then - dfile=zfile:close() - if trace_locating then - report_zip("finder: file %a found",queryname) - end - return specification.original - elseif trace_locating then - report_zip("finder: file %a not found",queryname) - end - elseif trace_locating then - report_zip("finder: unknown archive %a",archive) - end - end - end - if trace_locating then - report_zip("finder: %a not found",original) - end - return resolvers.finders.notfound() -end -function resolvers.openers.zip(specification) - local original=specification.original - local archive=specification.filename - if archive then - local query=url.query(specification.query) - local queryname=query.name - if queryname then - local zfile=zip.openarchive(archive) - if zfile then - if trace_locating then - report_zip("opener; archive %a opened",archive) - end - local dfile=zfile:open(queryname) - if dfile then - if trace_locating then - report_zip("opener: file %a found",queryname) - end - return resolvers.openers.helpers.textopener('zip',original,dfile) - elseif trace_locating then - report_zip("opener: file %a not found",queryname) - end - elseif trace_locating then - report_zip("opener: unknown archive %a",archive) - end - end - end - if trace_locating then - report_zip("opener: %a not found",original) - end - return resolvers.openers.notfound() -end -function resolvers.loaders.zip(specification) - local original=specification.original - local archive=specification.filename - if archive then - local query=url.query(specification.query) - local queryname=query.name - if queryname then - local zfile=zip.openarchive(archive) - if zfile then - if trace_locating then - report_zip("loader: archive %a opened",archive) - end - local dfile=zfile:open(queryname) - if dfile then - logs.show_load(original) - if trace_locating then - report_zip("loader; file %a loaded",original) - end - local s=dfile:read("*all") - dfile:close() - return true,s,#s - elseif trace_locating then - report_zip("loader: file %a not found",queryname) - end - elseif trace_locating then - report_zip("loader; unknown archive %a",archive) - end - end - end - if trace_locating then - report_zip("loader: %a not found",original) - end - return resolvers.openers.notfound() -end -function resolvers.usezipfile(archive) - local specification=resolvers.splitmethod(archive) - local archive=specification.filename - if archive and not registeredfiles[archive] then - local z=zip.openarchive(archive) - if z then - local instance=resolvers.instance - local tree=url.query(specification.query).tree or "" - if trace_locating then - report_zip("registering: archive %a",archive) - end - statistics.starttiming(instance) - resolvers.prependhash('zip',archive) - resolvers.extendtexmfvariable(archive) - registeredfiles[archive]=z - instance.files[archive]=resolvers.registerzipfile(z,tree) - statistics.stoptiming(instance) - elseif trace_locating then - report_zip("registering: unknown archive %a",archive) - end - elseif trace_locating then - report_zip("registering: archive %a not found",archive) - end -end -function resolvers.registerzipfile(z,tree) - local files,filter={},"" - if tree=="" then - filter="^(.+)/(.-)$" - else - filter=format("^%s/(.+)/(.-)$",tree) - end - if trace_locating then - report_zip("registering: using filter %a",filter) - end - local register,n=resolvers.registerfile,0 - for i in z:files() do - local path,name=match(i.filename,filter) - if path then - if name and name~='' then - register(files,name,path) - n=n+1 - else - end - else - register(files,i.filename,'') - n=n+1 - end - end - report_zip("registering: %s files registered",n) - return files -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-tre"] = package.loaded["data-tre"] or true - --- original size: 2508, stripped down to: 2074 - -if not modules then modules={} end modules ['data-tre']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local find,gsub,format=string.find,string.gsub,string.format -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local report_trees=logs.reporter("resolvers","trees") -local resolvers=resolvers -local done,found,notfound={},{},resolvers.finders.notfound -function resolvers.finders.tree(specification) - local spec=specification.filename - local fnd=found[spec] - if fnd==nil then - if spec~="" then - local path,name=file.dirname(spec),file.basename(spec) - if path=="" then path="." end - local hash=done[path] - if not hash then - local pattern=path.."/*" - hash=dir.glob(pattern) - done[path]=hash - end - local pattern="/"..gsub(name,"([%.%-%+])","%%%1").."$" - for k=1,#hash do - local v=hash[k] - if find(v,pattern) then - found[spec]=v - return v - end - end - end - fnd=notfound() - found[spec]=fnd - end - return fnd -end -function resolvers.locators.tree(specification) - local name=specification.filename - local realname=resolvers.resolve(name) - if realname and realname~='' and lfs.isdir(realname) then - if trace_locating then - report_trees("locator %a found",realname) - end - resolvers.appendhash('tree',name,false) - elseif trace_locating then - report_trees("locator %a not found",name) - end -end -function resolvers.hashers.tree(specification) - local name=specification.filename - if trace_locating then - report_trees("analysing %a",name) - end - resolvers.methodhandler("hashers",name) - resolvers.generators.file(specification) -end -resolvers.concatinators.tree=resolvers.concatinators.file -resolvers.generators.tree=resolvers.generators.file -resolvers.openers.tree=resolvers.openers.file -resolvers.loaders.tree=resolvers.loaders.file - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-sch"] = package.loaded["data-sch"] or true - --- original size: 6202, stripped down to: 5149 - -if not modules then modules={} end modules ['data-sch']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local load=load -local gsub,concat,format=string.gsub,table.concat,string.format -local finders,openers,loaders=resolvers.finders,resolvers.openers,resolvers.loaders -local trace_schemes=false trackers.register("resolvers.schemes",function(v) trace_schemes=v end) -local report_schemes=logs.reporter("resolvers","schemes") -local http=require("socket.http") -local ltn12=require("ltn12") -local resolvers=resolvers -local schemes=resolvers.schemes or {} -resolvers.schemes=schemes -local cleaners={} -schemes.cleaners=cleaners -local threshold=24*60*60 -directives.register("schemes.threshold",function(v) threshold=tonumber(v) or threshold end) -function cleaners.none(specification) - return specification.original -end -function cleaners.strip(specification) - return (gsub(specification.original,"[^%a%d%.]+","-")) -end -function cleaners.md5(specification) - return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path)) -end -local cleaner=cleaners.strip -directives.register("schemes.cleanmethod",function(v) cleaner=cleaners[v] or cleaners.strip end) -function resolvers.schemes.cleanname(specification) - local hash=cleaner(specification) - if trace_schemes then - report_schemes("hashing %a to %a",specification.original,hash) - end - return hash -end -local cached,loaded,reused,thresholds,handlers={},{},{},{},{} -local function runcurl(name,cachename) - local command="curl --silent --create-dirs --output "..cachename.." "..name - os.spawn(command) -end -local function fetch(specification) - local original=specification.original - local scheme=specification.scheme - local cleanname=schemes.cleanname(specification) - local cachename=caches.setfirstwritablefile(cleanname,"schemes") - if not cached[original] then - statistics.starttiming(schemes) - if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification)>(thresholds[protocol] or threshold)) then - cached[original]=cachename - local handler=handlers[scheme] - if handler then - if trace_schemes then - report_schemes("fetching %a, protocol %a, method %a",original,scheme,"built-in") - end - logs.flush() - handler(specification,cachename) - else - if trace_schemes then - report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl") - end - logs.flush() - runcurl(original,cachename) - end - end - if io.exists(cachename) then - cached[original]=cachename - if trace_schemes then - report_schemes("using cached %a, protocol %a, cachename %a",original,scheme,cachename) - end - else - cached[original]="" - if trace_schemes then - report_schemes("using missing %a, protocol %a",original,scheme) - end - end - loaded[scheme]=loaded[scheme]+1 - statistics.stoptiming(schemes) - else - if trace_schemes then - report_schemes("reusing %a, protocol %a",original,scheme) - end - reused[scheme]=reused[scheme]+1 - end - return cached[original] -end -local function finder(specification,filetype) - return resolvers.methodhandler("finders",fetch(specification),filetype) -end -local opener=openers.file -local loader=loaders.file -local function install(scheme,handler,newthreshold) - handlers [scheme]=handler - loaded [scheme]=0 - reused [scheme]=0 - finders [scheme]=finder - openers [scheme]=opener - loaders [scheme]=loader - thresholds[scheme]=newthreshold or threshold -end -schemes.install=install -local function http_handler(specification,cachename) - local tempname=cachename..".tmp" - local f=io.open(tempname,"wb") - local status,message=http.request { - url=specification.original, - sink=ltn12.sink.file(f) - } - if not status then - os.remove(tempname) - else - os.remove(cachename) - os.rename(tempname,cachename) - end - return cachename -end -install('http',http_handler) -install('https') -install('ftp') -statistics.register("scheme handling time",function() - local l,r,nl,nr={},{},0,0 - for k,v in table.sortedhash(loaded) do - if v>0 then - nl=nl+1 - l[nl]=k..":"..v - end - end - for k,v in table.sortedhash(reused) do - if v>0 then - nr=nr+1 - r[nr]=k..":"..v - end - end - local n=nl+nr - if n>0 then - l=nl>0 and concat(l) or "none" - r=nr>0 and concat(r) or "none" - return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s", - statistics.elapsedtime(schemes),n,threshold,l,r) - else - return nil - end -end) -local httprequest=http.request -local toquery=url.toquery -local function fetchstring(url,data) - local q=data and toquery(data) - if q then - url=url.."?"..q - end - local reply=httprequest(url) - return reply -end -schemes.fetchstring=fetchstring -function schemes.fetchtable(url,data) - local reply=fetchstring(url,data) - if reply then - local s=load("return "..reply) - if s then - return s() - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-lua"] = package.loaded["data-lua"] or true - --- original size: 4237, stripped down to: 3177 - -if not modules then modules={} end modules ['data-lua']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local resolvers,package=resolvers,package -local gsub=string.gsub -local concat=table.concat -local addsuffix=file.addsuffix -local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match -local luasuffixes={ 'tex','lua' } -local libsuffixes={ 'lib' } -local luaformats={ 'TEXINPUTS','LUAINPUTS' } -local libformats={ 'CLUAINPUTS' } -local helpers=package.helpers or {} -local methods=helpers.methods or {} -trackers.register("resolvers.libraries",function(v) helpers.trace=v end) -trackers.register("resolvers.locating",function(v) helpers.trace=v end) -helpers.report=logs.reporter("resolvers","libraries") -helpers.sequence={ - "already loaded", - "preload table", - "lua variable format", - "lib variable format", - "lua extra list", - "lib extra list", - "path specification", - "cpath specification", - "all in one fallback", - "not loaded", -} -local pattern=Cs(P("!")^0/""*(P("/")*P(-1)/"/"+P("/")^1/"/"+1)^0) -function helpers.cleanpath(path) - return resolvers.resolve(lpegmatch(pattern,path)) -end -local loadedaslib=helpers.loadedaslib -local getextraluapaths=package.extraluapaths -local getextralibpaths=package.extralibpaths -local registerpath=helpers.registerpath -local lualibfile=helpers.lualibfile -local luaformatpaths -local libformatpaths -local function getluaformatpaths() - if not luaformatpaths then - luaformatpaths={} - for i=1,#luaformats do - registerpath("lua format","lua",luaformatpaths,resolvers.expandedpathlistfromvariable(luaformats[i])) - end - end - return luaformatpaths -end -local function getlibformatpaths() - if not libformatpaths then - libformatpaths={} - for i=1,#libformats do - registerpath("lib format","lib",libformatpaths,resolvers.expandedpathlistfromvariable(libformats[i])) - end - end - return libformatpaths -end -local function loadedbyformat(name,rawname,suffixes,islib,what) - local trace=helpers.trace - local report=helpers.report - for i=1,#suffixes do - local format=suffixes[i] - local resolved=resolvers.findfile(name,format) or "" - if trace then - report("%s format, identifying %a using format %a",what,name,format) - end - if resolved~="" then - if trace then - report("%s format, %a found on %a",what,name,resolved) - end - if islib then - return loadedaslib(resolved,rawname) - else - return loadfile(resolved) - end - end - end -end -helpers.loadedbyformat=loadedbyformat -methods["lua variable format"]=function(name) - if helpers.trace then - helpers.report("%s format, checking %s paths","lua",#getluaformatpaths()) - end - return loadedbyformat(addsuffix(lualibfile(name),"lua"),name,luasuffixes,false,"lua") -end -methods["lib variable format"]=function(name) - if helpers.trace then - helpers.report("%s format, checking %s paths","lib",#getlibformatpaths()) - end - return loadedbyformat(addsuffix(lualibfile(name),os.libsuffix),name,libsuffixes,true,"lib") -end -resolvers.loadlualib=require - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-aux"] = package.loaded["data-aux"] or true - --- original size: 2431, stripped down to: 1996 - -if not modules then modules={} end modules ['data-aux']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local find=string.find -local type,next=type,next -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local resolvers=resolvers -local report_scripts=logs.reporter("resolvers","scripts") -function resolvers.updatescript(oldname,newname) - local scriptpath="context/lua" - newname=file.addsuffix(newname,"lua") - local oldscript=resolvers.cleanpath(oldname) - if trace_locating then - report_scripts("to be replaced old script %a",oldscript) - end - local newscripts=resolvers.findfiles(newname) or {} - if #newscripts==0 then - if trace_locating then - report_scripts("unable to locate new script") - end - else - for i=1,#newscripts do - local newscript=resolvers.cleanpath(newscripts[i]) - if trace_locating then - report_scripts("checking new script %a",newscript) - end - if oldscript==newscript then - if trace_locating then - report_scripts("old and new script are the same") - end - elseif not find(newscript,scriptpath) then - if trace_locating then - report_scripts("new script should come from %a",scriptpath) - end - elseif not (find(oldscript,file.removesuffix(newname).."$") or find(oldscript,newname.."$")) then - if trace_locating then - report_scripts("invalid new script name") - end - else - local newdata=io.loaddata(newscript) - if newdata then - if trace_locating then - report_scripts("old script content replaced by new content") - end - io.savedata(oldscript,newdata) - break - elseif trace_locating then - report_scripts("unable to load new script") - end - end - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-tmf"] = package.loaded["data-tmf"] or true - --- original size: 2600, stripped down to: 1627 - -if not modules then modules={} end modules ['data-tmf']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local resolvers=resolvers -local report_tds=logs.reporter("resolvers","tds") -function resolvers.load_tree(tree,resolve) - if type(tree)=="string" and tree~="" then - local getenv,setenv=resolvers.getenv,resolvers.setenv - local texos="texmf-"..os.platform - local oldroot=environment.texroot - local newroot=file.collapsepath(tree) - local newtree=file.join(newroot,texos) - local newpath=file.join(newtree,"bin") - if not lfs.isdir(newtree) then - report_tds("no %a under tree %a",texos,tree) - os.exit() - end - if not lfs.isdir(newpath) then - report_tds("no '%s/bin' under tree %a",texos,tree) - os.exit() - end - local texmfos=newtree - environment.texroot=newroot - environment.texos=texos - environment.texmfos=texmfos - if resolve then - resolvers.luacnfspec=resolvers.resolve(resolvers.luacnfspec) - end - setenv('SELFAUTOPARENT',newroot) - setenv('SELFAUTODIR',newtree) - setenv('SELFAUTOLOC',newpath) - setenv('TEXROOT',newroot) - setenv('TEXOS',texos) - setenv('TEXMFOS',texmfos) - setenv('TEXMFCNF',resolvers.luacnfspec,true) - setenv('PATH',newpath..io.pathseparator..getenv('PATH')) - report_tds("changing from root %a to %a",oldroot,newroot) - report_tds("prepending %a to PATH",newpath) - report_tds("setting TEXMFCNF to %a",resolvers.luacnfspec) - report_tds() - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-lst"] = package.loaded["data-lst"] or true - --- original size: 2654, stripped down to: 2301 - -if not modules then modules={} end modules ['data-lst']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local find,concat,upper,format=string.find,table.concat,string.upper,string.format -local fastcopy,sortedpairs=table.fastcopy,table.sortedpairs -resolvers.listers=resolvers.listers or {} -local resolvers=resolvers -local report_lists=logs.reporter("resolvers","lists") -local function tabstr(str) - if type(str)=='table' then - return concat(str," | ") - else - return str - end -end -function resolvers.listers.variables(pattern) - local instance=resolvers.instance - local environment=instance.environment - local variables=instance.variables - local expansions=instance.expansions - local pattern=upper(pattern or "") - local configured={} - local order=instance.order - for i=1,#order do - for k,v in next,order[i] do - if v~=nil and configured[k]==nil then - configured[k]=v - end - end - end - local env=fastcopy(environment) - local var=fastcopy(variables) - local exp=fastcopy(expansions) - for key,value in sortedpairs(configured) do - if key~="" and (pattern=="" or find(upper(key),pattern)) then - report_lists(key) - report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset") - report_lists(" var: %s",tabstr(configured[key]) or "unset") - report_lists(" exp: %s",tabstr(expansions[key]) or "unset") - report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset") - end - end - instance.environment=fastcopy(env) - instance.variables=fastcopy(var) - instance.expansions=fastcopy(exp) -end -local report_resolved=logs.reporter("system","resolved") -function resolvers.listers.configurations() - local configurations=resolvers.instance.specification - for i=1,#configurations do - report_resolved("file : %s",resolvers.resolve(configurations[i])) - end - report_resolved("") - local list=resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec)) - for i=1,#list do - local li=resolvers.resolve(list[i]) - if lfs.isdir(li) then - report_resolved("path - %s",li) - else - report_resolved("path + %s",li) - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-lib"] = package.loaded["util-lib"] or true - --- original size: 11549, stripped down to: 5905 - -if not modules then modules={} end modules ['util-lib']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files", -} -local gsub,find=string.gsub,string.find -local pathpart,nameonly,joinfile=file.pathpart,file.nameonly,file.join -local findfile,findfiles=resolvers and resolvers.findfile,resolvers and resolvers.findfiles -local loaded=package.loaded -local report_swiglib=logs.reporter("swiglib") -local trace_swiglib=false trackers.register("resolvers.swiglib",function(v) trace_swiglib=v end) -local done=false -local function requireswiglib(required,version) - local trace_swiglib=trace_swiglib or package.helpers.trace - local library=loaded[required] - if library==nil then - if trace_swiglib then - report_swiglib("requiring library %a with version %a",required,version or "any") - end - local required_full=gsub(required,"%.","/") - local required_path=pathpart(required_full) - local required_base=nameonly(required_full) - local required_name=required_base.."."..os.libsuffix - local version=type(version)=="string" and version~="" and version or false - local engine=environment.ownmain or false - if trace_swiglib and not done then - local list=resolvers.expandedpathlistfromvariable("lib") - for i=1,#list do - report_swiglib("tds path %i: %s",i,list[i]) - end - end - local function found(locate,asked_library,how,...) - if trace_swiglib then - report_swiglib("checking %s: %a",how,asked_library) - end - return locate(asked_library,...) - end - local function check(locate,...) - local found=nil - if version then - local asked_library=joinfile(required_path,version,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) - end - found=locate(asked_library,...) - end - if not found or found=="" then - local asked_library=joinfile(required_path,required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","with version",asked_library) - end - found=locate(asked_library,...) - end - return found and found~="" and found or false - end - local function attempt(checkpattern) - if trace_swiglib then - report_swiglib("checking tds lib paths strictly") - end - local found=findfile and check(findfile,"lib") - if found and (not checkpattern or find(found,checkpattern)) then - return found - end - if trace_swiglib then - report_swiglib("checking tds lib paths with wildcard") - end - local asked_library=joinfile(required_path,".*",required_name) - if trace_swiglib then - report_swiglib("checking %s: %a","latest version",asked_library) - end - local list=findfiles(asked_library,"lib",true) - if list and #list>0 then - table.sort(list) - local found=list[#list] - if found and (not checkpattern or find(found,checkpattern)) then - return found - end - end - if trace_swiglib then - report_swiglib("checking lib paths") - end - package.extralibpath(environment.ownpath) - local paths=package.libpaths() - for i=1,#paths do - local found=check(lfs.isfile) - if found and (not checkpattern or find(found,checkpattern)) then - return found - end - end - return false - end - local found_library=nil - if engine then - if trace_swiglib then - report_swiglib("attemp 1, engine %a",engine) - end - found_library=attempt("/"..engine.."/") - if not found_library then - if trace_swiglib then - report_swiglib("attemp 2, no engine",asked_library) - end - found_library=attempt() - end - else - found_library=attempt() - end - if not found_library then - if trace_swiglib then - report_swiglib("not found: %a",required) - end - library=false - else - local path=pathpart(found_library) - local base=nameonly(found_library) - dir.push(path) - if trace_swiglib then - report_swiglib("found: %a",found_library) - end - local message=nil - local opener="luaopen_"..required_base - library,message=package.loadlib(found_library,opener) - local libtype=type(library) - if libtype=="function" then - library=library() - else - report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library") - library=false - end - dir.pop() - end - if not library then - report_swiglib("unknown: %a",required) - elseif trace_swiglib then - report_swiglib("stored: %a",required) - end - loaded[required]=library - else - report_swiglib("reused: %a",required) - end - return library -end -local savedrequire=require -function require(name,version) - if find(name,"^swiglib%.") then - return requireswiglib(name,version) - else - return savedrequire(name) - end -end -local swiglibs={} -local initializer="core" -function swiglib(name,version) - local library=swiglibs[name] - if not library then - statistics.starttiming(swiglibs) - if trace_swiglib then - report_swiglib("loading %a",name) - end - if not find(name,"%."..initializer.."$") then - fullname="swiglib."..name.."."..initializer - else - fullname="swiglib."..name - end - library=requireswiglib(fullname,version) - swiglibs[name]=library - statistics.stoptiming(swiglibs) - end - return library -end -statistics.register("used swiglibs",function() - if next(swiglibs) then - return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs)) - end -end) - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["luat-sta"] = package.loaded["luat-sta"] or true - --- original size: 5703, stripped down to: 2507 - -if not modules then modules={} end modules ['luat-sta']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local gmatch,match=string.gmatch,string.match -local type=type -states=states or {} -local states=states -states.data=states.data or {} -local data=states.data -states.hash=states.hash or {} -local hash=states.hash -states.tag=states.tag or "" -states.filename=states.filename or "" -function states.save(filename,tag) - tag=tag or states.tag - filename=file.addsuffix(filename or states.filename,'lus') - io.savedata(filename, - "-- generator : luat-sta.lua\n".."-- state tag : "..tag.."\n\n"..table.serialize(data[tag or states.tag] or {},true) - ) -end -function states.load(filename,tag) - states.filename=filename - states.tag=tag or "whatever" - states.filename=file.addsuffix(states.filename,'lus') - data[states.tag],hash[states.tag]=(io.exists(filename) and dofile(filename)) or {},{} -end -local function set_by_tag(tag,key,value,default,persistent) - local d,h=data[tag],hash[tag] - if d then - if type(d)=="table" then - local dkey,hkey=key,key - local pre,post=match(key,"(.+)%.([^%.]+)$") - if pre and post then - for k in gmatch(pre,"[^%.]+") do - local dk=d[k] - if not dk then - dk={} - d[k]=dk - elseif type(dk)=="string" then - break - end - d=dk - end - dkey,hkey=post,key - end - if value==nil then - value=default - elseif value==false then - elseif persistent then - value=value or d[dkey] or default - else - value=value or default - end - d[dkey],h[hkey]=value,value - elseif type(d)=="string" then - data[tag],hash[tag]=value,value - end - end -end -local function get_by_tag(tag,key,default) - local h=hash[tag] - if h and h[key] then - return h[key] - else - local d=data[tag] - if d then - for k in gmatch(key,"[^%.]+") do - local dk=d[k] - if dk~=nil then - d=dk - else - return default - end - end - if d==false then - return false - else - return d or default - end - end - end -end -states.set_by_tag=set_by_tag -states.get_by_tag=get_by_tag -function states.set(key,value,default,persistent) - set_by_tag(states.tag,key,value,default,persistent) -end -function states.get(key,default) - return get_by_tag(states.tag,key,default) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["luat-fmt"] = package.loaded["luat-fmt"] or true - --- original size: 5951, stripped down to: 4922 - -if not modules then modules={} end modules ['luat-fmt']={ - version=1.001, - comment="companion to mtxrun", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format=string.format -local concat=table.concat -local quoted=string.quoted -local luasuffixes=utilities.lua.suffixes -local report_format=logs.reporter("resolvers","formats") -local function primaryflags() - local trackers=environment.argument("trackers") - local directives=environment.argument("directives") - local flags={} - if trackers and trackers~="" then - flags={ "--trackers="..quoted(trackers) } - end - if directives and directives~="" then - flags={ "--directives="..quoted(directives) } - end - if environment.argument("jit") then - flags={ "--jiton" } - end - return concat(flags," ") -end -function environment.make_format(name) - local engine=environment.ownmain or "luatex" - local olddir=dir.current() - local path=caches.getwritablepath("formats",engine) or "" - if path~="" then - lfs.chdir(path) - end - report_format("using format path %a",dir.current()) - local texsourcename=file.addsuffix(name,"mkiv") - local fulltexsourcename=resolvers.findfile(texsourcename,"tex") or "" - if fulltexsourcename=="" then - texsourcename=file.addsuffix(name,"tex") - fulltexsourcename=resolvers.findfile(texsourcename,"tex") or "" - end - if fulltexsourcename=="" then - report_format("no tex source file with name %a (mkiv or tex)",name) - lfs.chdir(olddir) - return - else - report_format("using tex source file %a",fulltexsourcename) - end - local texsourcepath=dir.expandname(file.dirname(fulltexsourcename)) - local specificationname=file.replacesuffix(fulltexsourcename,"lus") - local fullspecificationname=resolvers.findfile(specificationname,"tex") or "" - if fullspecificationname=="" then - specificationname=file.join(texsourcepath,"context.lus") - fullspecificationname=resolvers.findfile(specificationname,"tex") or "" - end - if fullspecificationname=="" then - report_format("unknown stub specification %a",specificationname) - lfs.chdir(olddir) - return - end - local specificationpath=file.dirname(fullspecificationname) - local usedluastub=nil - local usedlualibs=dofile(fullspecificationname) - if type(usedlualibs)=="string" then - usedluastub=file.join(file.dirname(fullspecificationname),usedlualibs) - elseif type(usedlualibs)=="table" then - report_format("using stub specification %a",fullspecificationname) - local texbasename=file.basename(name) - local luastubname=file.addsuffix(texbasename,luasuffixes.lua) - local lucstubname=file.addsuffix(texbasename,luasuffixes.luc) - report_format("creating initialization file %a",luastubname) - utilities.merger.selfcreate(usedlualibs,specificationpath,luastubname) - if utilities.lua.compile(luastubname,lucstubname) and lfs.isfile(lucstubname) then - report_format("using compiled initialization file %a",lucstubname) - usedluastub=lucstubname - else - report_format("using uncompiled initialization file %a",luastubname) - usedluastub=luastubname - end - else - report_format("invalid stub specification %a",fullspecificationname) - lfs.chdir(olddir) - return - end - local command=format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform=="unix" and "\\\\" or "\\") - report_format("running command: %s\n",command) - os.spawn(command) - local pattern=file.removesuffix(file.basename(usedluastub)).."-*.mem" - local mp=dir.glob(pattern) - if mp then - for i=1,#mp do - local name=mp[i] - report_format("removing related mplib format %a",file.basename(name)) - os.remove(name) - end - end - lfs.chdir(olddir) -end -function environment.run_format(name,data,more) - if name and name~="" then - local engine=environment.ownmain or "luatex" - local barename=file.removesuffix(name) - local fmtname=caches.getfirstreadablefile(file.addsuffix(barename,"fmt"),"formats",engine) - if fmtname=="" then - fmtname=resolvers.findfile(file.addsuffix(barename,"fmt")) or "" - end - fmtname=resolvers.cleanpath(fmtname) - if fmtname=="" then - report_format("no format with name %a",name) - else - local barename=file.removesuffix(name) - local luaname=file.addsuffix(barename,"luc") - if not lfs.isfile(luaname) then - luaname=file.addsuffix(barename,"lua") - end - if not lfs.isfile(luaname) then - report_format("using format name %a",fmtname) - report_format("no luc/lua file with name %a",barename) - else - local command=format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more~="" and quoted(more) or "") - report_format("running command: %s",command) - os.spawn(command) - end - end - end -end - - -end -- of closure - --- used libraries : l-lua.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua --- skipped libraries : - --- original bytes : 689993 --- stripped bytes : 244562 - --- end library merge - --- We need this hack till luatex is fixed. --- --- for k,v in pairs(arg) do print(k,v) end - -if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then - arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil -end - --- End of hack. - -local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find -local concat = table.concat - -local ownname = environment and environment.ownname or arg[0] or 'mtxrun.lua' -local ownpath = gsub(match(ownname,"^(.+)[\\/].-$") or ".","\\","/") -local owntree = environment and environment.ownpath or ownpath - -local ownlibs = { -- order can be made better - - 'l-lua.lua', - 'l-package.lua', - 'l-lpeg.lua', - 'l-function.lua', - 'l-string.lua', - 'l-table.lua', - 'l-io.lua', - 'l-number.lua', - 'l-set.lua', - 'l-os.lua', - 'l-file.lua', - 'l-gzip.lua', - 'l-md5.lua', - 'l-url.lua', - 'l-dir.lua', - 'l-boolean.lua', - 'l-unicode.lua', - 'l-math.lua', - - 'util-str.lua', -- code might move to l-string - 'util-tab.lua', - 'util-sto.lua', - 'util-prs.lua', - 'util-fmt.lua', - - 'trac-set.lua', - 'trac-log.lua', - 'trac-inf.lua', -- was before trac-set - 'trac-pro.lua', -- not really needed - 'util-lua.lua', -- indeed here? - 'util-deb.lua', - - 'util-mrg.lua', - 'util-tpl.lua', - - 'util-env.lua', - 'luat-env.lua', -- can come before inf (as in mkiv) - - 'lxml-tab.lua', - 'lxml-lpt.lua', - -- 'lxml-ent.lua', - 'lxml-mis.lua', - 'lxml-aux.lua', - 'lxml-xml.lua', - - 'trac-xml.lua', - - 'data-ini.lua', - 'data-exp.lua', - 'data-env.lua', - 'data-tmp.lua', - 'data-met.lua', - 'data-res.lua', - 'data-pre.lua', - 'data-inp.lua', - 'data-out.lua', - 'data-fil.lua', - 'data-con.lua', - 'data-use.lua', --- 'data-tex.lua', --- 'data-bin.lua', - 'data-zip.lua', - 'data-tre.lua', - 'data-sch.lua', - 'data-lua.lua', - 'data-aux.lua', -- updater - 'data-tmf.lua', - 'data-lst.lua', - - 'util-lib.lua', -- swiglib - - 'luat-sta.lua', - 'luat-fmt.lua', - -} - --- c:/data/develop/tex-context/tex/texmf-win64/bin/../../texmf-context/tex/context/base/data-tmf.lua --- c:/data/develop/context/sources/data-tmf.lua - -local ownlist = { - -- '.', - -- ownpath , - owntree .. "/../../../../context/sources", -- HH's development path - owntree .. "/../../texmf-local/tex/context/base", - owntree .. "/../../texmf-context/tex/context/base", - owntree .. "/../../texmf/tex/context/base", - owntree .. "/../../../texmf-local/tex/context/base", - owntree .. "/../../../texmf-context/tex/context/base", - owntree .. "/../../../texmf/tex/context/base", -} - -if ownpath == "." then table.remove(ownlist,1) end - -own = { - name = ownname, - path = ownpath, - tree = owntree, - list = ownlist, - libs = ownlibs, -} - -local function locate_libs() - for l=1,#ownlibs do - local lib = ownlibs[l] - for p =1,#ownlist do - local pth = ownlist[p] - local filename = pth .. "/" .. lib - local found = lfs.isfile(filename) - if found then - package.path = package.path .. ";" .. pth .. "/?.lua" -- in case l-* does a require - return pth - end - end - end -end - -local function load_libs() - local found = locate_libs() - if found then - for l=1,#ownlibs do - local filename = found .. "/" .. ownlibs[l] - local codeblob = loadfile(filename) - if codeblob then - codeblob() - end - end - else - resolvers = nil - end -end - -if not resolvers then - load_libs() -end - -if not resolvers then - print("") - print("Mtxrun is unable to start up due to lack of libraries. You may") - print("try to run 'lua mtxrun.lua --selfmerge' in the path where this") - print("script is located (normally under ..../scripts/context/lua) which") - print("will make this script library independent.") - os.exit() -end - --- verbosity - ------ e_verbose = environment.arguments["verbose"] - -local e_verbose = false - --- some common flags (also passed through environment) - -local e_silent = environment.argument("silent") -local e_noconsole = environment.argument("noconsole") - -local e_trackers = environment.argument("trackers") -local e_directives = environment.argument("directives") -local e_experiments = environment.argument("experiments") - -if e_silent == true then - e_silent = "*" -end - -if type(e_silent) == "string" then - if type(e_directives) == "string" then - e_directives = format("%s,logs.blocked={%s}",e_directives,e_silent) - else - e_directives = format("logs.blocked={%s}",e_silent) - end -end - -if e_noconsole then - if type(e_directives) == "string" then - e_directives = format("%s,logs.target=file",e_directives) - else - e_directives = format("logs.target=file") - end -end - -if e_trackers then trackers .enable(e_trackers) end -if e_directives then directives .enable(e_directives) end -if e_experiments then experiments.enable(e_experiments) end - -if not environment.trackers then environment.trackers = e_trackers end -if not environment.directives then environment.directives = e_directives end -if not environment.experiments then environment.experiments = e_experiments end - --- - -local instance = resolvers.reset() - -local helpinfo = [[ -<?xml version="1.0" ?> -<application> - <metadata> - <entry name="name">mtxrun</entry> - <entry name="detail">ConTeXt TDS Runner Tool</entry> - <entry name="version">1.31</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="script"><short>run an mtx script (lua prefered method) (<ref name="noquotes"/>), no script gives list</short></flag> - <flag name="execute"><short>run a script or program (texmfstart method) (<ref name="noquotes"/>)</short></flag> - <flag name="resolve"><short>resolve prefixed arguments</short></flag> - <flag name="ctxlua"><short>run internally (using preloaded libs)</short></flag> - <flag name="internal"><short>run script using built in libraries (same as <ref name="ctxlua"/>)</short></flag> - <flag name="locate"><short>locate given filename in database (default) or system (<ref name="first"/> <ref name="all"/> <ref name="detail"/>)</short></flag> - </subcategory> - <subcategory> - <flag name="autotree"><short>use texmf tree cf. env texmfstart_tree or texmfstarttree</short></flag> - <flag name="tree" value="pathtotree"><short>use given texmf tree (default file: setuptex.tmf)</short></flag> - <flag name="environment" value="name"><short>use given (tmf) environment file</short></flag> - <flag name="path" value="runpath"><short>go to given path before execution</short></flag> - <flag name="ifchanged" value="filename"><short>only execute when given file has changed (md checksum)</short></flag> - <flag name="iftouched" value="old,new"><short>only execute when given file has changed (time stamp)</short></flag> - </subcategory> - <subcategory> - <flag name="makestubs"><short>create stubs for (context related) scripts</short></flag> - <flag name="removestubs"><short>remove stubs (context related) scripts</short></flag> - <flag name="stubpath" value="binpath"><short>paths where stubs wil be written</short></flag> - <flag name="windows"><short>create windows (mswin) stubs</short></flag> - <flag name="unix"><short>create unix (linux) stubs</short></flag> - </subcategory> - <subcategory> - <flag name="verbose"><short>give a bit more info</short></flag> - <flag name="trackers" value="list"><short>enable given trackers</short></flag> - <flag name="progname" value="str"><short>format or backend</short></flag> - </subcategory> - <subcategory> - <flag name="edit"><short>launch editor with found file</short></flag> - <flag name="launch"><short>launch files like manuals, assumes os support (<ref name="all"/>)</short></flag> - </subcategory> - <subcategory> - <flag name="timedrun"><short>run a script and time its run</short></flag> - <flag name="autogenerate"><short>regenerate databases if needed (handy when used to run context in an editor)</short></flag> - </subcategory> - <subcategory> - <flag name="usekpse"><short>use kpse as fallback (when no mkiv and cache installed, often slower)</short></flag> - <flag name="forcekpse"><short>force using kpse (handy when no mkiv and cache installed but less functionality)</short></flag> - </subcategory> - <subcategory> - <flag name="prefixes"><short>show supported prefixes</short></flag> - </subcategory> - <subcategory> - <flag name="generate"><short>generate file database</short></flag> - </subcategory> - <subcategory> - <flag name="variables"><short>show configuration variables</short></flag> - <flag name="configurations"><short>show configuration order</short></flag> - </subcategory> - <subcategory> - <flag name="directives"><short>show (known) directives</short></flag> - <flag name="trackers"><short>show (known) trackers</short></flag> - <flag name="experiments"><short>show (known) experiments</short></flag> - </subcategory> - <subcategory> - <flag name="expand-braces"><short>expand complex variable</short></flag> - <flag name="expand-path"><short>expand variable (resolve paths)</short></flag> - <flag name="expand-var"><short>expand variable (resolve references)</short></flag> - <flag name="show-path"><short>show path expansion of ...</short></flag> - <flag name="var-value"><short>report value of variable</short></flag> - <flag name="find-file"><short>report file location</short></flag> - <flag name="find-path"><short>report path of file</short></flag> - </subcategory> - <subcategory> - <flag name="pattern" value="string"><short>filter variables</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtxrun", - banner = "ConTeXt TDS Runner Tool 1.31", - helpinfo = helpinfo, -} - -local report = application.report - -messages = messages or { } -- for the moment - -runners = runners or { } -- global (might become local) - -runners.applications = { - ["lua"] = "luatex --luaonly", - ["luc"] = "luatex --luaonly", - ["pl"] = "perl", - ["py"] = "python", - ["rb"] = "ruby", -} - -runners.suffixes = { - 'rb', 'lua', 'py', 'pl' -} - -runners.registered = { - texexec = { 'texexec.rb', false }, -- context mkii runner (only tool not to be luafied) - texutil = { 'texutil.rb', true }, -- old perl based index sorter for mkii (old versions need it) - texfont = { 'texfont.pl', true }, -- perl script that makes mkii font metric files - texfind = { 'texfind.pl', false }, -- perltk based tex searching tool, mostly used at pragma - texshow = { 'texshow.pl', false }, -- perltk based context help system, will be luafied - -- texwork = { 'texwork.pl', false }, -- perltk based editing environment, only used at pragma - makempy = { 'makempy.pl', true }, - mptopdf = { 'mptopdf.pl', true }, - pstopdf = { 'pstopdf.rb', true }, -- converts ps (and some more) images, does some cleaning (replaced) - -- examplex = { 'examplex.rb', false }, - concheck = { 'concheck.rb', false }, - runtools = { 'runtools.rb', true }, - textools = { 'textools.rb', true }, - tmftools = { 'tmftools.rb', true }, - ctxtools = { 'ctxtools.rb', true }, - rlxtools = { 'rlxtools.rb', true }, - pdftools = { 'pdftools.rb', true }, - mpstools = { 'mpstools.rb', true }, - -- exatools = { 'exatools.rb', true }, - xmltools = { 'xmltools.rb', true }, - -- luatools = { 'luatools.lua', true }, - mtxtools = { 'mtxtools.rb', true }, - pdftrimwhite = { 'pdftrimwhite.pl', false }, -} - -runners.launchers = { - windows = { }, - unix = { }, -} - --- like runners.libpath("framework"): looks on script's subpath - -function runners.libpath(...) - package.prepend_libpath(file.dirname(environment.ownscript),...) - package.prepend_libpath(file.dirname(environment.ownname) ,...) -end - -function runners.prepare() - local checkname = environment.argument("ifchanged") - if type(checkname) == "string" and checkname ~= "" then - local oldchecksum = file.loadchecksum(checkname) - local newchecksum = file.checksum(checkname) - if oldchecksum == newchecksum then - if e_verbose then - report("file '%s' is unchanged",checkname) - end - return "skip" - elseif e_verbose then - report("file '%s' is changed, processing started",checkname) - end - file.savechecksum(checkname) - end - local touchname = environment.argument("iftouched") - if type(touchname) == "string" and touchname ~= "" then - local oldname, newname = string.splitup(touchname, ",") - if oldname and newname and oldname ~= "" and newname ~= "" then - if not file.needs_updating(oldname,newname) then - if e_verbose then - report("file '%s' and '%s' have same age",oldname,newname) - end - return "skip" - elseif e_verbose then - report("file '%s' is older than '%s'",oldname,newname) - end - end - end - local runpath = environment.argument("path") - if type(runpath) == "string" and not lfs.chdir(runpath) then - report("unable to change to path '%s'",runpath) - return "error" - end - runners.prepare = function() end - return "run" -end - -function runners.execute_script(fullname,internal,nosplit) - local noquote = environment.argument("noquotes") - if fullname and fullname ~= "" then - local state = runners.prepare() - if state == 'error' then - return false - elseif state == 'skip' then - return true - elseif state == "run" then - local path, name, suffix = file.splitname(fullname) - local result = "" - if path ~= "" then - result = fullname - elseif name then - name = gsub(name,"^int[%a]*:",function() - internal = true - return "" - end ) - name = gsub(name,"^script:","") - if suffix == "" and runners.registered[name] and runners.registered[name][1] then - name = runners.registered[name][1] - suffix = file.suffix(name) - end - if suffix == "" then - -- loop over known suffixes - for _,s in pairs(runners.suffixes) do - result = resolvers.findfile(name .. "." .. s, 'texmfscripts') - if result ~= "" then - break - end - end - elseif runners.applications[suffix] then - result = resolvers.findfile(name, 'texmfscripts') - else - -- maybe look on path - result = resolvers.findfile(name, 'other text files') - end - end - if result and result ~= "" then - if not no_split then - local before, after = environment.splitarguments(fullname) -- already done - environment.arguments_before, environment.arguments_after = before, after - end - if internal then - arg = { } for _,v in pairs(environment.arguments_after) do arg[#arg+1] = v end - environment.ownscript = result - dofile(result) - else -local texmfcnf = resolvers.getenv("TEXMFCNF") -if not texmfcnf or texmfcnf == "" then - texmfcnf = resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.resolve(resolvers.luacnfspec))) - resolvers.setenv("TEXMFCNF",table.concat(texmfcnf,";")) -- for running texexec etc (after tl change to texmf-dist) -end - local binary = runners.applications[file.suffix(result)] - result = string.quoted(string.unquoted(result)) - -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then - -- result = '"' .. result .. '"' - -- end - if binary and binary ~= "" then - result = binary .. " " .. result - end - local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote) - if e_verbose then - report() - report("executing: %s",command) - report() - report() - io.flush() - end - -- no os.exec because otherwise we get the wrong return value - local code = os.execute(command) -- maybe spawn - if code == 0 then - return true - else - if binary then - binary = file.addsuffix(binary,os.binsuffix) - for p in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do - if lfs.isfile(file.join(p,binary)) then - return false - end - end - report() - report("This script needs '%s' which seems not to be installed.",binary) - report() - end - return false - end - end - end - end - end - return false -end - -function runners.execute_program(fullname) - local noquote = environment.argument("noquotes") - if fullname and fullname ~= "" then - local state = runners.prepare() - if state == 'error' then - return false - elseif state == 'skip' then - return true - elseif state == "run" then - local before, after = environment.splitarguments(fullname) - for k=1,#after do after[k] = resolvers.resolve(after[k]) end - environment.initializearguments(after) - fullname = gsub(fullname,"^bin:","") - local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "") - report() - report("executing: %s",command) - report() - report() - io.flush() - local code = os.exec(command) -- (fullname,unpack(after)) does not work / maybe spawn - return code == 0 - end - end - return false -end - --- the --usekpse flag will fallback (not default) on kpse (hm, we can better update mtx-stubs) - -local windows_stub = '@echo off\013\010setlocal\013\010set ownpath=%%~dp0%%\013\010texlua "%%ownpath%%mtxrun.lua" --usekpse --execute %s %%*\013\010endlocal\013\010' -local unix_stub = '#!/bin/sh\010mtxrun --usekpse --execute %s \"$@\"\010' - -function runners.handle_stubs(create) - local stubpath = environment.argument('stubpath') or '.' -- 'auto' no longer subpathssupported - local windows = environment.argument('windows') or environment.argument('mswin') or false - local unix = environment.argument('unix') or environment.argument('linux') or false - if not windows and not unix then - if os.platform == "unix" then - unix = true - else - windows = true - end - end - for _,v in pairs(runners.registered) do - local name, doit = v[1], v[2] - if doit then - local base = gsub(file.basename(name), "%.(.-)$", "") - if create then - if windows then - io.savedata(file.join(stubpath,base..".bat"),format(windows_stub,name)) - report("windows stub for '%s' created",base) - end - if unix then - io.savedata(file.join(stubpath,base),format(unix_stub,name)) - report("unix stub for '%s' created",base) - end - else - if windows and (os.remove(file.join(stubpath,base..'.bat')) or os.remove(file.join(stubpath,base..'.cmd'))) then - report("windows stub for '%s' removed", base) - end - if unix and (os.remove(file.join(stubpath,base)) or os.remove(file.join(stubpath,base..'.sh'))) then - report("unix stub for '%s' removed",base) - end - end - end - end -end - -function runners.resolve_string(filename) - if filename and filename ~= "" then - runners.report_location(resolvers.resolve(filename)) - end -end - --- differs from texmfstart where locate appends .com .exe .bat ... todo - -function runners.locate_file(filename) -- was given file but only searches in tree - if filename and filename ~= "" then - if environment.argument("first") then - runners.report_location(resolvers.findfile(filename)) - -- resolvers.dowithfilesandreport(resolvers.findfile,filename) - elseif environment.argument("all") then - local result, status = resolvers.findfiles(filename) - if status and environment.argument("detail") then - runners.report_location(status) - else - runners.report_location(result) - end - else - runners.report_location(resolvers.findgivenfile(filename)) - -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename) - end - end -end - -function runners.locate_platform() - runners.report_location(os.platform) -end - -function runners.report_location(result) - if type(result) == "table" then - for i=1,#result do - if i > 1 then - io.write("\n") - end - io.write(result[i]) - end - else - io.write(result) - end -end - -function runners.edit_script(filename) -- we assume that gvim is present on most systems (todo: also in cnf file) - local editor = os.getenv("MTXRUN_EDITOR") or os.getenv("TEXMFSTART_EDITOR") or os.getenv("EDITOR") or 'gvim' - local rest = resolvers.resolve(filename) - if rest ~= "" then - local command = editor .. " " .. rest - if e_verbose then - report() - report("starting editor: %s",command) - report() - report() - end - os.launch(command) - end -end - -function runners.save_script_session(filename, list) - local t = { } - for i=1,#list do - local key = list[i] - t[key] = environment.arguments[key] - end - io.savedata(filename,table.serialize(t,true)) -end - -function runners.load_script_session(filename) - if lfs.isfile(filename) then - local t = io.loaddata(filename) - if t then - t = loadstring(t) - if t then t = t() end - for key, value in pairs(t) do - environment.arguments[key] = value - end - end - end -end - -function resolvers.launch(str) - -- maybe we also need to test on mtxrun.launcher.suffix environment - -- variable or on windows consult the assoc and ftype vars and such - local launchers = runners.launchers[os.platform] if launchers then - local suffix = file.suffix(str) if suffix then - local runner = launchers[suffix] if runner then - str = runner .. " " .. str - end - end - end - os.launch(str) -end - -function runners.launch_file(filename) - trackers.enable("resolvers.locating") - local allresults = environment.arguments["all"] - local pattern = environment.arguments["pattern"] - if not pattern or pattern == "" then - pattern = filename - end - if not pattern or pattern == "" then - report("provide name or --pattern=") - else - local t = resolvers.findfiles(pattern,nil,allresults) - if not t or #t == 0 then - t = resolvers.findfiles("*/" .. pattern,nil,allresults) - end - if not t or #t == 0 then - t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults) - end - if t and #t > 0 then - if allresults then - for _, v in pairs(t) do - report("launching %s", v) - resolvers.launch(v) - end - else - report("launching %s", t[1]) - resolvers.launch(t[1]) - end - else - report("no match for %s", pattern) - end - end -end - -local mtxprefixes = { - { "^mtx%-", "mtx-" }, - { "^mtx%-t%-", "mtx-t-" }, -} - -function runners.find_mtx_script(filename) - local function found(name) - local path = file.dirname(name) - if path and path ~= "" then - return false - else - local fullname = own and own.path and file.join(own.path,name) - return io.exists(fullname) and fullname - end - end - filename = file.addsuffix(filename,"lua") - local basename = file.removesuffix(file.basename(filename)) - local suffix = file.suffix(filename) - -- qualified path, raw name - local fullname = file.is_qualified_path(filename) and io.exists(filename) and filename - if fullname and fullname ~= "" then - return fullname - end - -- current path, raw name - fullname = "./" .. filename - fullname = io.exists(fullname) and fullname - if fullname and fullname ~= "" then - return fullname - end - -- mtx- prefix checking - for i=1,#mtxprefixes do - local mtxprefix = mtxprefixes[i] - mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2] - -- context namespace, mtx-<filename> - fullname = mtxprefix .. filename - fullname = found(fullname) or resolvers.findfile(fullname) - if fullname and fullname ~= "" then - return fullname - end - -- context namespace, mtx-<filename>s - fullname = mtxprefix .. basename .. "s" .. "." .. suffix - fullname = found(fullname) or resolvers.findfile(fullname) - if fullname and fullname ~= "" then - return fullname - end - -- context namespace, mtx-<filename minus trailing s> - fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix - fullname = found(fullname) or resolvers.findfile(fullname) - if fullname and fullname ~= "" then - return fullname - end - end - -- context namespace, just <filename> - fullname = resolvers.findfile(filename) - return fullname -end - -function runners.register_arguments(...) - local arguments = environment.arguments_after - local passedon = { ... } - for i=#passedon,1,-1 do - local pi = passedon[i] - if pi then - table.insert(arguments,1,pi) - end - end -end - -function runners.execute_ctx_script(filename,...) - runners.register_arguments(...) - local arguments = environment.arguments_after - local fullname = runners.find_mtx_script(filename) or "" - if file.suffix(fullname) == "cld" then - -- handy in editors where we force --autopdf - report("running cld script: %s",filename) - table.insert(arguments,1,fullname) - table.insert(arguments,"--autopdf") - fullname = runners.find_mtx_script("context") or "" - end - -- retry after generate but only if --autogenerate - if fullname == "" and environment.argument("autogenerate") then -- might become the default - instance.renewcache = true - trackers.enable("resolvers.locating") - resolvers.load() - -- - fullname = runners.find_mtx_script(filename) or "" - end - -- that should do it - if fullname ~= "" then - local state = runners.prepare() - if state == 'error' then - return false - elseif state == 'skip' then - return true - elseif state == "run" then - -- load and save ... kind of undocumented - arg = { } for _,v in pairs(arguments) do arg[#arg+1] = resolvers.resolve(v) end - environment.initializearguments(arg) - local loadname = environment.arguments['load'] - if loadname then - if type(loadname) ~= "string" then loadname = file.basename(fullname) end - loadname = file.replacesuffix(loadname,"cfg") - runners.load_script_session(loadname) - end - filename = environment.files[1] - if e_verbose then - report("using script: %s\n",fullname) - end - environment.ownscript = fullname - dofile(fullname) - local savename = environment.arguments['save'] - if savename then - local save_list = runners.save_list - if save_list and next(save_list) then - if type(savename) ~= "string" then savename = file.basename(fullname) end - savename = file.replacesuffix(savename,"cfg") - runners.save_script_session(savename,save_list) - end - end - return true - end - else - if filename == "" or filename == "help" then - local context = resolvers.findfile("mtx-context.lua") - trackers.enable("resolvers.locating") - if context ~= "" then - local result = dir.glob((gsub(context,"mtx%-context","mtx-*"))) -- () needed - local valid = { } - table.sort(result) - for i=1,#result do - local scriptname = result[i] - local scriptbase = match(scriptname,".*mtx%-([^%-]-)%.lua") - if scriptbase then - local data = io.loaddata(scriptname) -local application = match(data,"local application.-=.-(%{.-%})") -if application then - application = loadstring("return " .. application) - if application then - application = application() - local banner = application.banner - if banner then - local description, version = match(banner,"^(.-) ([%d.]+)$") - if description then - valid[#valid+1] = { scriptbase, version, description } - else - valid[#valid+1] = { scriptbase, "", banner } - end - end - end -end - end - end - if #valid > 0 then - application.identify() - report("no script name given, known scripts:") - report() - for k=1,#valid do - local v = valid[k] - report("%-12s %4s %s",v[1],v[2],v[3]) - end - end - else - report("no script name given") - end - else - filename = file.addsuffix(filename,"lua") - if file.is_qualified_path(filename) then - report("unknown script '%s'",filename) - else - report("unknown script '%s' or 'mtx-%s'",filename,filename) - end - end - return false - end -end - -function runners.prefixes() - application.identify() - report() - report(concat(resolvers.allprefixes(true)," ")) -end - -function runners.timedrun(filename) -- just for me - if filename and filename ~= "" then - runners.timed(function() os.execute(filename) end) - end -end - -function runners.timed(action) - statistics.timed(action) -end - -function runners.associate(filename) - os.launch(filename) -end - -function runners.gethelp(filename) - local url = environment.argument("url") - if url and url ~= "" then - local command = string.gsub(environment.argument("command") or "unknown","^%s*\\*(.-)%s*$","%1") - url = utilities.templates.replace(url,{ command = command }) - os.launch(url) - else - report("no --url given") - end -end - --- this is a bit dirty ... first we store the first filename and next we --- split the arguments so that we only see the ones meant for this script --- ... later we will use the second half - -local filename = environment.files[1] or "" -local ok = true - -local before, after = environment.splitarguments(filename) -environment.arguments_before, environment.arguments_after = before, after -environment.initializearguments(before) - -instance.lsrmode = environment.argument("lsr") or false - -e_verbose = environment.arguments["verbose"] -- delayed till here (we need the ones before script) - -if e_verbose then - trackers.enable("resolvers.locating") -end - --- maybe the unset has to go to this level - -local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))] - -local e_argument = environment.argument - -if e_argument("timedlog") then - logs.settimedlog() -end - -if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then - - resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF - - os.setenv("engine","") - os.setenv("progname","") - - local remapper = { - otf = "opentype fonts", - ttf = "truetype fonts", - ttc = "truetype fonts", - pfb = "type1 fonts", - other = "other text files", - } - - local progname = e_argument("progname") or 'context' - - local function kpse_initialized() - texconfig.kpse_init = true - local t = os.clock() - local k = kpse.original.new("luatex",progname) - local dummy = k:find_file("mtxrun.lua") -- so that we're initialized - report("kpse fallback with progname '%s' initialized in %s seconds",progname,os.clock()-t) - kpse_initialized = function() return k end - return k - end - - local findfile = resolvers.findfile - local showpath = resolvers.showpath - - if e_argument("forcekpse") then - - function resolvers.findfile(name,kind) - return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or "" - end - function resolvers.showpath(name) - return (kpse_initialized():show_path(name)) or "" - end - - elseif e_argument("usekpse") or is_mkii_stub then - - resolvers.load() - - function resolvers.findfile(name,kind) - local found = findfile(name,kind) or "" - if found ~= "" then - return found - else - return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or "" - end - end - function resolvers.showpath(name) - local found = showpath(name) or "" - if found ~= "" then - return found - else - return (kpse_initialized():show_path(name)) or "" - end - end - - end - - function runners.loadbase() - end - -else - - function runners.loadbase(...) - if not resolvers.load(...) then - report("forcing cache reload") - instance.renewcache = true - trackers.enable("resolvers.locating") - if not resolvers.load(...) then - report("the resolver databases are not present or outdated") - end - end - end - - resolvers.load_tree(e_argument('tree'),e_argument("resolve")) - -end - --- joke .. reminds me of messing with gigi terminals - -if e_argument("ansi") then - - local formatters = string.formatters - - logs.setformatters { - report_yes = formatters["[1;32m%-15s [0;1m|[0m %s"], - report_nop = formatters["[1;32m%-15s [0;1m|[0m"], - subreport_yes = formatters["[1;32m%-15s [0;1m|[1;31m %s [0;1m|[0m %s"], - subreport_nop = formatters["[1;32m%-15s [0;1m|[1;31m %s [0;1m|[0m"], - status_yes = formatters["[1;32m%-15s [0;1m:[0m %s\n"], - status_nop = formatters["[1;32m%-15s [0;1m:[0m\n"], - } - - local script = e_argument("script") or e_argument("scripts") - - if type(script) == "string" then - logs.writer("]0;"..script.."") -- for Alan to test - end - -end - -if e_argument("script") or e_argument("scripts") then - - -- run a script by loading it (using libs), pass args - - if e_argument("nofiledatabase") then - -- handy for mtx-update - else - runners.loadbase() - end - if is_mkii_stub then - ok = runners.execute_script(filename,false,true) - else - ok = runners.execute_ctx_script(filename) - end - -elseif e_argument("selfmerge") then - - -- embed used libraries - - runners.loadbase() - local found = locate_libs() - - if found then - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfmerge(mtxrun,own.libs,{ found }) - application.report("runner updated on resolved path: %s",mtxrun) - else - utilities.merger.selfmerge(own.name,own.libs,{ found }) - application.report("runner updated on relative path: %s",own.name) - end - end - -elseif e_argument("selfclean") then - - -- remove embedded libraries - - runners.loadbase() - - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfclean(mtxrun) - application.report("runner cleaned on resolved path: %s",mtxrun) - else - utilities.merger.selfclean(own.name) - application.report("runner cleaned on relative path: %s",own.name) - end - -elseif e_argument("selfupdate") then - - runners.loadbase() - trackers.enable("resolvers.locating") - resolvers.updatescript(own.name,"mtxrun") - -elseif e_argument("ctxlua") or e_argument("internal") then - - -- run a script by loading it (using libs) - - runners.loadbase() - ok = runners.execute_script(filename,true) - -elseif e_argument("execute") then - - -- execute script - - runners.loadbase() - ok = runners.execute_script(filename) - -elseif e_argument("direct") then - - -- equals bin: - - runners.loadbase() - ok = runners.execute_program(filename) - -elseif e_argument("edit") then - - -- edit file - - runners.loadbase() - runners.edit_script(filename) - -elseif e_argument("launch") then - - runners.loadbase() - runners.launch_file(filename) - -elseif e_argument("associate") then - - runners.associate(filename) - -elseif e_argument("gethelp") then - - runners.gethelp() - -elseif e_argument("makestubs") then - - -- make stubs (depricated) - - runners.handle_stubs(true) - -elseif e_argument("removestubs") then - - -- remove stub (depricated) - - runners.loadbase() - runners.handle_stubs(false) - -elseif e_argument("resolve") then - - -- resolve string - - runners.loadbase() - runners.resolve_string(filename) - -elseif e_argument("locate") then - - -- locate file (only database) - - runners.loadbase() - runners.locate_file(filename) - -elseif e_argument("platform") or e_argument("show-platform") then - - -- locate platform - - runners.loadbase() - runners.locate_platform() - -elseif e_argument("prefixes") then - - runners.loadbase() - runners.prefixes() - -elseif e_argument("timedrun") then - - -- locate platform - - runners.loadbase() - runners.timedrun(filename) - -elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then - - -- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename) - - resolvers.load("nofiles") - resolvers.listers.variables(e_argument("pattern")) - -elseif e_argument("configurations") or e_argument("show-configurations") then - - -- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename) - - resolvers.load("nofiles") - resolvers.listers.configurations() - -elseif e_argument("find-file") then - - -- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename) - - resolvers.load() - local e_all = e_argument("all") - local e_pattern = e_argument("pattern") - local e_format = e_argument("format") - local finder = e_all and resolvers.findfiles or resolvers.findfile - if not e_pattern then - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(finder,environment.files,e_format) - elseif type(e_pattern) == "string" then - resolvers.dowithfilesandreport(finder,{ e_pattern },e_format) - end - -elseif e_argument("find-path") then - - -- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename) - - resolvers.load() - local path = resolvers.findpath(filename, instance.my_format) - if e_verbose then - report(path) - else - print(path) - end - -elseif e_argument("expand-braces") then - - -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files) - -elseif e_argument("expand-path") then - - -- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.expandpath, environment.files) - -elseif e_argument("expand-var") or e_argument("expand-variable") then - - -- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.expansion, environment.files) - -elseif e_argument("show-path") or e_argument("path-value") then - - -- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.showpath, environment.files) - -elseif e_argument("var-value") or e_argument("show-value") then - - -- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.variable,environment.files) - -elseif e_argument("format-path") then - - -- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename) - - resolvers.load() - report(caches.getwritablepath("format")) - -elseif e_argument("pattern") then - - -- luatools - - runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename) - -elseif e_argument("generate") then - - -- luatools - - if filename and filename ~= "" then - resolvers.load("nofiles") - trackers.enable("resolvers.locating") - resolvers.renew(filename) - else - instance.renewcache = true - trackers.enable("resolvers.locating") - resolvers.load() - end - - e_verbose = true - -elseif e_argument("make") or e_argument("ini") or e_argument("compile") then - - -- luatools: runners.execute_ctx_script("mtx-base","--make",filename) - - resolvers.load() - trackers.enable("resolvers.locating") - environment.make_format(filename) - -elseif e_argument("run") then - - -- luatools - - runners.execute_ctx_script("mtx-base","--run",filename) - -elseif e_argument("fmt") then - - -- luatools - - runners.execute_ctx_script("mtx-base","--fmt",filename) - -elseif e_argument("help") and filename=='base' then - - -- luatools - - runners.execute_ctx_script("mtx-base","--help") - -elseif e_argument("version") then - - application.version() - - application.report("source path",environment.ownbin) - -elseif e_argument("directives") then - - directives.show() - -elseif e_argument("trackers") then - - trackers.show() - -elseif e_argument("experiments") then - - experiments.show() - -elseif e_argument("exporthelp") then - - runners.loadbase() - application.export(e_argument("exporthelp"),filename) - -elseif e_argument("help") or filename=='help' or filename == "" then - - application.help() - -elseif find(filename,"^bin:") then - - runners.loadbase() - ok = runners.execute_program(filename) - -elseif is_mkii_stub then - - -- execute mkii script - - runners.loadbase() - ok = runners.execute_script(filename,false,true) - -elseif false then - - runners.loadbase() - ok = runners.execute_ctx_script(filename) - if not ok then - ok = runners.execute_script(filename) - end - -elseif environment.files[1] == 'texmfcnf.lua' then -- so that we don't need to load mtx-base - - resolvers.load("nofiles") - resolvers.listers.configurations() - -else - runners.loadbase() - runners.execute_ctx_script("mtx-base",filename) - -end - -if e_verbose then - report() - report("elapsed lua time: %0.3f seconds",os.runtime()) -end - -if os.type ~= "windows" then - texio.write("\n") -- is this still valid? -end - -if ok == false then ok = 1 elseif ok == true or ok == nil then ok = 0 end - --- os.exit(ok,true) -- true forces a cleanup in 5.2+ - -os.exit(ok) -- true forces a cleanup in 5.2+ but reports a wrong number then diff --git a/scripts/context/stubs/win64/mtxrunjit.exe b/scripts/context/stubs/win64/mtxrunjit.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/mtxrunjit.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/mtxworks.exe b/scripts/context/stubs/win64/mtxworks.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/mtxworks.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/pstopdf.exe b/scripts/context/stubs/win64/pstopdf.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/pstopdf.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/texexec.exe b/scripts/context/stubs/win64/texexec.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/texexec.exe +++ /dev/null diff --git a/scripts/context/stubs/win64/texmfstart.exe b/scripts/context/stubs/win64/texmfstart.exe Binary files differdeleted file mode 100644 index 93290a6e0..000000000 --- a/scripts/context/stubs/win64/texmfstart.exe +++ /dev/null diff --git a/tex/context/base/anch-bar.mkiv b/tex/context/base/anch-bar.mkiv index 501507b3b..c7c6190be 100644 --- a/tex/context/base/anch-bar.mkiv +++ b/tex/context/base/anch-bar.mkiv @@ -81,6 +81,9 @@ \let\setupsidebars\setupsidebar \unexpanded\def\startsidebar + {\dosingleempty\anch_sidebars_start} + +\unexpanded\def\startsidebar {\dodoubleempty\anch_sidebars_start} \def\anch_sidebars_start[#1][#2]% @@ -120,7 +123,7 @@ \d_anch_sidebars_distance\dimexpr\scratchdimen+\numexpr\m_level-\plusone\relax\dimexpr\scratchdistance\relax\relax \fi \fi - \startpositionoverlay{\v!text-1}% + \startpositionoverlay{text-1}% \normalexpanded{\setMPpositiongraphicrange % maybe expand in definition {b:sidebar:\the\c_anch_sidebars_n}% {e:sidebar:\the\c_anch_sidebars_n}% @@ -208,6 +211,9 @@ \unexpanded\def\startmarginrule {\dosingleempty\anch_marginrules_start} +\unexpanded\def\startmarginrule + {\dosingleempty\anch_marginrules_start} + \def\anch_marginrules_start[#1]% pretty inefficient checking {\edef\m_anch_marginrules_kind{#1}% \ifx\m_anch_marginrules_kind\empty diff --git a/tex/context/base/anch-pos.lua b/tex/context/base/anch-pos.lua index 0bd945c8a..9cc9fb128 100644 --- a/tex/context/base/anch-pos.lua +++ b/tex/context/base/anch-pos.lua @@ -30,25 +30,15 @@ local texsp = tex.sp ----- texsp = string.todimen -- because we cache this is much faster but no rounding local texgetcount = tex.getcount +local texgetbox = tex.getbox local texsetcount = tex.setcount local texget = tex.get local pdf = pdf -- h and v are variables local setmetatableindex = table.setmetatableindex - -local nuts = nodes.nuts - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getlist = nuts.getlist -local getbox = nuts.getbox -local getskip = nuts.getskip - -local find_tail = nuts.tail - -local new_latelua = nuts.pool.latelua -local new_latelua_node = nodes.pool.latelua +local new_latelua = nodes.pool.latelua +local find_tail = node.slide local variables = interfaces.variables local v_text = variables.text @@ -312,13 +302,13 @@ function commands.bcolumn(tag,register) -- name will change insert(columns,tag) column = tag if register then - context(new_latelua_node(f_b_column(tag))) + context(new_latelua(f_b_column(tag))) end end function commands.ecolumn(register) -- name will change if register then - context(new_latelua_node(f_e_column())) + context(new_latelua(f_e_column())) end remove(columns) column = columns[#columns] @@ -350,10 +340,10 @@ function jobpositions.markregionbox(n,tag,correct) nofregions = nofregions + 1 tag = f_region(nofregions) end - local box = getbox(n) - local w = getfield(box,"width") - local h = getfield(box,"height") - local d = getfield(box,"depth") + local box = texgetbox(n) + local w = box.width + local h = box.height + local d = box.depth tobesaved[tag] = { p = true, x = true, @@ -365,18 +355,18 @@ function jobpositions.markregionbox(n,tag,correct) local push = new_latelua(f_b_region(tag)) local pop = new_latelua(f_e_region(tostring(correct))) -- todo: check if tostring is needed with formatter -- maybe we should construct a hbox first (needs experimenting) so that we can avoid some at the tex end - local head = getlist(box) + local head = box.list if head then local tail = find_tail(head) - setfield(head,"prev",push) - setfield(push,"next",head) - setfield(pop,"prev",tail) - setfield(tail,"next",pop) + head.prev = push + push.next = head + pop .prev = tail + tail.next = pop else -- we can have a simple push/pop - setfield(push,"next",pop) - setfield(pop,"prev",push) + push.next = pop + pop.prev = push end - setfield(box,"list",push) + box.list = push end function jobpositions.enhance(name) @@ -385,7 +375,7 @@ end function commands.pos(name,t) tobesaved[name] = t - context(new_latelua_node(f_enhance(name))) + context(new_latelua(f_enhance(name))) end local nofparagraphs = 0 @@ -393,19 +383,19 @@ local nofparagraphs = 0 function commands.parpos() -- todo: relate to localpar (so this is an intermediate variant) nofparagraphs = nofparagraphs + 1 texsetcount("global","c_anch_positions_paragraph",nofparagraphs) - local strutbox = getbox("strutbox") + local strutbox = texgetbox("strutbox") local t = { p = true, c = true, r = true, x = true, y = true, - h = getfield(strutbox,"height"), - d = getfield(strutbox,"depth"), + h = strutbox.height, + d = strutbox.depth, hs = texget("hsize"), } - local leftskip = getfield(getskip("leftskip"),"width") - local rightskip = getfield(getskip("rightskip"),"width") + local leftskip = texget("leftskip").width + local rightskip = texget("rightskip").width local hangindent = texget("hangindent") local hangafter = texget("hangafter") local parindent = texget("parindent") @@ -430,7 +420,7 @@ function commands.parpos() -- todo: relate to localpar (so this is an intermedia end local tag = f_p_tag(nofparagraphs) tobesaved[tag] = t - context(new_latelua_node(f_enhance(tag))) + context(new_latelua(f_enhance(tag))) end function commands.posxy(name) -- can node.write be used here? @@ -442,7 +432,7 @@ function commands.posxy(name) -- can node.write be used here? y = true, n = nofparagraphs > 0 and nofparagraphs or nil, } - context(new_latelua_node(f_enhance(name))) + context(new_latelua(f_enhance(name))) end function commands.poswhd(name,w,h,d) @@ -457,7 +447,7 @@ function commands.poswhd(name,w,h,d) d = d, n = nofparagraphs > 0 and nofparagraphs or nil, } - context(new_latelua_node(f_enhance(name))) + context(new_latelua(f_enhance(name))) end function commands.posplus(name,w,h,d,extra) @@ -473,22 +463,22 @@ function commands.posplus(name,w,h,d,extra) n = nofparagraphs > 0 and nofparagraphs or nil, e = extra, } - context(new_latelua_node(f_enhance(name))) + context(new_latelua(f_enhance(name))) end function commands.posstrut(name,w,h,d) - local strutbox = getbox("strutbox") + local strutbox = texgetbox("strutbox") tobesaved[name] = { p = true, c = column, r = true, x = true, y = true, - h = getfield(strutbox,"height"), - d = getfield(strutbox,"depth"), + h = strutbox.height, + d = strutbox.depth, n = nofparagraphs > 0 and nofparagraphs or nil, } - context(new_latelua_node(f_enhance(name))) + context(new_latelua(f_enhance(name))) end function jobpositions.getreserved(tag,n) diff --git a/tex/context/base/attr-ini.mkiv b/tex/context/base/attr-ini.mkiv index 3f49e67a9..9dfa7baae 100644 --- a/tex/context/base/attr-ini.mkiv +++ b/tex/context/base/attr-ini.mkiv @@ -85,7 +85,7 @@ %D For the moment we put this here (later it will move to where it's used): \definesystemattribute [state] -\definesystemattribute [color] [public] % global +\definesystemattribute [color] [public] \definesystemattribute [colormodel] [public,global] \definesystemattribute [skip] \definesystemattribute [penalty] diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua index d4133396b..18a339247 100644 --- a/tex/context/base/back-exp.lua +++ b/tex/context/base/back-exp.lua @@ -95,22 +95,10 @@ local a_reference = attributes.private('reference') local a_textblock = attributes.private("textblock") -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getsubtype = nuts.getsubtype -local getfont = nuts.getfont -local getchar = nuts.getchar -local getlist = nuts.getlist -local getid = nuts.getid -local getfield = nuts.getfield -local getattr = nuts.getattr - -local setattr = nuts.setattr - -local traverse_id = nuts.traverse_id -local traverse_nodes = nuts.traverse +local traverse_id = node.traverse_id +local traverse_nodes = node.traverse +local slide_nodelist = node.slide +local locate_node = nodes.locate local references = structures.references local structurestags = structures.tags @@ -454,26 +442,13 @@ local function checkdocument(root) if data then for i=1,#data do local di = data[i] - local tg = di.tg - if tg == "noexport" then - local ud = userdata[di.fulltag] - local comment = ud and ud.comment - if comment then - di.element = "comment" - di.data = { { content = comment } } - ud.comment = nil - else - data[i] = false - -- di.element = "" - -- di.data = nil - end - elseif di.content then - -- okay - elseif tg == "ignore" then + if di.content then + -- ok + elseif di.tg == "ignore" then di.element = "" checkdocument(di) else - checkdocument(di) -- new, else no noexport handling + -- can't happen end end end @@ -1210,28 +1185,23 @@ function structurestags.settabulatecell(align) end end -local function hascontent(data) - for i=1,#data do - local di = data[i] - if not di then - -- - elseif di.content then - return true - else - local d = di.data - if d and #d > 0 and hascontent(d) then - return true - end - end - end -end - function extras.tabulate(result,element,detail,n,fulltag,di) local data = di.data for i=1,#data do local di = data[i] - if di.tg == "tabulaterow" and not hascontent(di.data) then - di.element = "" -- or simply remove + if di.tg == "tabulaterow" then + local did = di.data + local content = false + for i=1,#did do + local d = did[i].data + if d and #d > 0 and d[1].content then + content = true + break + end + end + if not content then + di.element = "" -- or simply remove + end end end end @@ -1784,9 +1754,9 @@ local function pushentry(current) end end -local function pushcontent(oldparagraph,newparagraph) +local function pushcontent(currentparagraph,newparagraph) if nofcurrentcontent > 0 then - if oldparagraph then + if currentparagraph then if currentcontent[nofcurrentcontent] == "\n" then if trace_export then report_export("%w<!-- removing newline -->",currentdepth) @@ -1796,9 +1766,9 @@ local function pushcontent(oldparagraph,newparagraph) end local content = concat(currentcontent,"",1,nofcurrentcontent) if content == "" then - -- omit; when oldparagraph we could push, remove spaces, pop - elseif somespace[content] and oldparagraph then - -- omit; when oldparagraph we could push, remove spaces, pop + -- omit; when currentparagraph we could push, remove spaces, pop + elseif somespace[content] and currentparagraph then + -- omit; when currentparagraph we could push, remove spaces, pop else local olddepth, newdepth local list = taglist[currentattribute] @@ -1807,7 +1777,7 @@ local function pushcontent(oldparagraph,newparagraph) end local td = tree.data local nd = #td - td[nd+1] = { parnumber = oldparagraph or currentparagraph, content = content } + td[nd+1] = { parnumber = currentparagraph, content = content } if trace_export then report_export("%w<!-- start content with length %s -->",currentdepth,#content) report_export("%w%s",currentdepth,(gsub(content,"\n","\\n"))) @@ -1821,10 +1791,10 @@ local function pushcontent(oldparagraph,newparagraph) end nofcurrentcontent = 0 end - if oldparagraph then + if currentparagraph then pushentry(makebreaklist(currentnesting)) if trace_export then - report_export("%w<!-- break added betweep paragraph %a and %a -->",currentdepth,oldparagraph,newparagraph) + report_export("%w<!-- break added betweep paragraph %a and %a -->",currentdepth,currentparagraph,newparagraph) end end end @@ -1856,25 +1826,25 @@ end local function collectresults(head,list) -- is last used (we also have currentattribute) local p for n in traverse_nodes(head) do - local id = getid(n) -- 14: image, 8: literal (mp) + local id = n.id -- 14: image, 8: literal (mp) if id == glyph_code then - local at = getattr(n,a_tagged) + local at = n[a_tagged] if not at then -- we need to tag the pagebody stuff as being valid skippable -- -- report_export("skipping character: %C (no attribute)",n.char) else -- we could add tonunicodes for ligatures (todo) - local components = getfield(n,"components") + local components = n.components if components then -- we loose data collectresults(components,nil) else - local c = getchar(n) + local c = n.char if last ~= at then local tl = taglist[at] pushcontent() currentnesting = tl - currentparagraph = getattr(n,a_taggedpar) + currentparagraph = n[a_taggedpar] currentattribute = at last = at pushentry(currentnesting) @@ -1883,13 +1853,13 @@ local function collectresults(head,list) -- is last used (we also have currentat end -- We need to intercept this here; maybe I will also move this -- to a regular setter at the tex end. - local r = getattr(n,a_reference) + local r = n[a_reference] if r then referencehash[tl[#tl]] = r -- fulltag end -- elseif last then - local ap = getattr(n,a_taggedpar) + local ap = n[a_taggedpar] if ap ~= currentparagraph then pushcontent(currentparagraph,ap) pushentry(currentnesting) @@ -1904,7 +1874,7 @@ local function collectresults(head,list) -- is last used (we also have currentat report_export("%w<!-- processing glyph %C tagged %a) -->",currentdepth,c,at) end end - local s = getattr(n,a_exportstatus) + local s = n[a_exportstatus] if s then c = s end @@ -1913,7 +1883,7 @@ local function collectresults(head,list) -- is last used (we also have currentat report_export("%w<!-- skipping last glyph -->",currentdepth) end elseif c == 0x20 then - local a = getattr(n,a_characters) + local a = n[a_characters] nofcurrentcontent = nofcurrentcontent + 1 if a then if trace_export then @@ -1924,7 +1894,7 @@ local function collectresults(head,list) -- is last used (we also have currentat currentcontent[nofcurrentcontent] = " " end else - local fc = fontchar[getfont(n)] + local fc = fontchar[n.font] if fc then fc = fc and fc[c] if fc then @@ -1949,23 +1919,20 @@ local function collectresults(head,list) -- is last used (we also have currentat end elseif id == disc_code then -- probably too late if keephyphens then - local pre = getfield(n,"pre") - if pre and not getnext(pre) and getid(pre) == glyph_code and getchar(pre) == hyphencode then + local pre = n.pre + if pre and not pre.next and pre.id == glyph_code and pre.char == hyphencode then nofcurrentcontent = nofcurrentcontent + 1 currentcontent[nofcurrentcontent] = hyphen end end - local replace = getfield(n,"replace") - if replace then - collectresults(replace,nil) - end + collectresults(n.replace,nil) elseif id == glue_code then -- we need to distinguish between hskips and vskips - local ca = getattr(n,a_characters) + local ca = n[a_characters] if ca == 0 then -- skip this one ... already converted special character (node-acc) elseif ca then - local a = getattr(n,a_tagged) + local a = n[a_tagged] if a then local c = specialspaces[ca] if last ~= a then @@ -1975,13 +1942,13 @@ local function collectresults(head,list) -- is last used (we also have currentat end pushcontent() currentnesting = tl - currentparagraph = getattr(n,a_taggedpar) + currentparagraph = n[a_taggedpar] currentattribute = a last = a pushentry(currentnesting) -- no reference check (see above) elseif last then - local ap = getattr(n,a_taggedpar) + local ap = n[a_taggedpar] if ap ~= currentparagraph then pushcontent(currentparagraph,ap) pushentry(currentnesting) @@ -2002,11 +1969,11 @@ local function collectresults(head,list) -- is last used (we also have currentat currentcontent[nofcurrentcontent] = c end else - local subtype = getsubtype(n) + local subtype = n.subtype if subtype == userskip_code then - if getfield(getfield(n,"spec"),"width") > threshold then + if n.spec.width > threshold then if last and not somespace[currentcontent[nofcurrentcontent]] then - local a = getattr(n,a_tagged) + local a = n[a_tagged] if a == last then if trace_export then report_export("%w<!-- injecting spacing 5a -->",currentdepth) @@ -2033,7 +2000,7 @@ local function collectresults(head,list) -- is last used (we also have currentat end elseif subtype == spaceskip_code or subtype == xspaceskip_code then if not somespace[currentcontent[nofcurrentcontent]] then - local a = getattr(n,a_tagged) + local a = n[a_tagged] if a == last then if trace_export then report_export("%w<!-- injecting spacing 7 (stay in element) -->",currentdepth) @@ -2062,7 +2029,7 @@ local function collectresults(head,list) -- is last used (we also have currentat nofcurrentcontent = nofcurrentcontent - 1 end elseif not somespace[r] then - local a = getattr(n,a_tagged) + local a = n[a_tagged] if a == last then if trace_export then report_export("%w<!-- injecting spacing 1 (end of line, stay in element) -->",currentdepth) @@ -2090,9 +2057,9 @@ local function collectresults(head,list) -- is last used (we also have currentat end end elseif id == hlist_code or id == vlist_code then - local ai = getattr(n,a_image) + local ai = n[a_image] if ai then - local at = getattr(n,a_tagged) + local at = n[a_tagged] if nofcurrentcontent > 0 then pushcontent() pushentry(currentnesting) -- ?? @@ -2105,21 +2072,18 @@ local function collectresults(head,list) -- is last used (we also have currentat currentparagraph = nil else -- we need to determine an end-of-line - local list = getlist(n) - if list then - collectresults(list,n) - end + collectresults(n.list,n) end elseif id == kern_code then - local kern = getfield(n,"kern") + local kern = n.kern if kern > 0 then local limit = threshold - if p and getid(p) == glyph_code then - limit = fontquads[getfont(p)] / 4 + if p and p.id == glyph_code then + limit = fontquads[p.font] / 4 end if kern > limit then if last and not somespace[currentcontent[nofcurrentcontent]] then - local a = getattr(n,a_tagged) + local a = n[a_tagged] if a == last then if not somespace[currentcontent[nofcurrentcontent]] then if trace_export then @@ -2159,7 +2123,7 @@ function nodes.handlers.export(head) -- hooks into the page builder end -- continueexport() restart = true - collectresults(tonut(head)) + collectresults(head) if trace_export then report_export("%w<!-- stop flushing page -->",currentdepth) end @@ -2169,12 +2133,12 @@ end function builders.paragraphs.tag(head) noftextblocks = noftextblocks + 1 - for n in traverse_id(hlist_code,tonut(head)) do - local subtype = getsubtype(n) + for n in traverse_id(hlist_code,head) do + local subtype = n.subtype if subtype == line_code then - setattr(n,a_textblock,noftextblocks) + n[a_textblock] = noftextblocks elseif subtype == glue_code or subtype == kern_code then - setattr(n,a_textblock,0) + n[a_textblock] = 0 end end return false diff --git a/tex/context/base/bibl-tra.lua b/tex/context/base/bibl-tra.lua index 75dc3e86f..82f8dc2aa 100644 --- a/tex/context/base/bibl-tra.lua +++ b/tex/context/base/bibl-tra.lua @@ -10,7 +10,7 @@ if not modules then modules = { } end modules ['bibl-tra'] = { -- temporary hack, needed for transition -if not publications then +if not punlications then local hacks = utilities.storage.allocate() diff --git a/tex/context/base/buff-ver.mkiv b/tex/context/base/buff-ver.mkiv index 6c4fb6fc1..bdde5df9d 100644 --- a/tex/context/base/buff-ver.mkiv +++ b/tex/context/base/buff-ver.mkiv @@ -758,9 +758,8 @@ \buff_verbatim_setup_line_numbering \buff_verbatim_initialize_typing_one \buff_verbatim_initialize_typing_two - \dostarttagged\t!verbatimblock{#1}% \beginofverbatimlines - \dostarttagged\t!verbatimlines\empty + \dostarttagged\t!verbatimblock{#1}% \ctxcommand{typebuffer { name = "#2", strip = "\typingparameter\c!strip", @@ -773,7 +772,6 @@ }}% \dostoptagged \endofverbatimlines - \dostoptagged \stoppacked \typingparameter\c!after} diff --git a/tex/context/base/char-def.lua b/tex/context/base/char-def.lua index 3e1d56009..9642d1736 100644 --- a/tex/context/base/char-def.lua +++ b/tex/context/base/char-def.lua @@ -1829,9 +1829,7 @@ characters.data={ direction="on", linebreak="al", mathclass="topaccent", - mathfiller="barfill", mathname="bar", - mathmleq=0x203E, specials={ "compat", 0x0020, 0x0304 }, unicodeslot=0x00AF, }, diff --git a/tex/context/base/char-utf.lua b/tex/context/base/char-utf.lua index d406b8bfe..95ed48279 100644 --- a/tex/context/base/char-utf.lua +++ b/tex/context/base/char-utf.lua @@ -357,55 +357,44 @@ function utffilters.collapse(str,filename) -- we can make high a seperate pass return str end --- function utffilters.decompose(str) --- if str and str ~= "" then --- local nstr = #str --- if nstr > 1 then --- -- if initialize then -- saves a call --- -- initialize() --- -- end --- local tokens, t, done, n = { }, 0, false, 0 --- for s in utfcharacters(str) do --- local dec = decomposed[s] --- if dec then --- if not done then --- if n > 0 then --- for s in utfcharacters(str) do --- if n == 0 then --- break --- else --- t = t + 1 --- tokens[t] = s --- n = n - 1 --- end --- end --- end --- done = true --- end --- t = t + 1 --- tokens[t] = dec --- elseif done then --- t = t + 1 --- tokens[t] = s --- else --- n = n + 1 --- end --- end --- if done then --- return concat(tokens) -- seldom called --- end --- end --- end --- return str --- end - -local tree = lpeg.utfchartabletopattern(table.keys(decomposed)) -local finder = lpeg.finder(tree,false,true) -local replacer = lpeg.replacer(tree,decomposed,false,true) - -function utffilters.decompose(str) -- 3 to 4 times faster than the above - if str and str ~= "" and #str > 1 and lpegmatch(finder,str) then - return lpegmatch(replacer,str) +function utffilters.decompose(str) + if str and str ~= "" then + local nstr = #str + if nstr > 1 then + -- if initialize then -- saves a call + -- initialize() + -- end + local tokens, t, done, n = { }, 0, false, 0 + for s in utfcharacters(str) do + local dec = decomposed[s] + if dec then + if not done then + if n > 0 then + for s in utfcharacters(str) do + if n == 1 then + break + else + t = t + 1 + tokens[t] = s + n = n - 1 + end + end + end + done = true + end + t = t + 1 + tokens[t] = dec + elseif done then + t = t + 1 + tokens[t] = s + else + n = n + 1 + end + end + if done then + return concat(tokens) -- seldom called + end + end end return str end diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv index 733afc6d0..134b1f08a 100644 --- a/tex/context/base/cont-new.mkiv +++ b/tex/context/base/cont-new.mkiv @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2014.02.14 17:07} +\newcontextversion{2014.01.03 00:40} %D This file is loaded at runtime, thereby providing an excellent place for %D hacks, patches, extensions and new features. @@ -24,16 +24,6 @@ %D Maybe: -% \appendtoks -% \inheritmaintextcolor -% \to \everybeforenoteinsert - -% \appendtoks -% \inheritmaintextcolor -% \to \everymargindatacontent - -%D Maybe: - \unexpanded\def\tightvbox{\dowithnextbox{\dp\nextbox\zeropoint\box\nextbox}\vbox} \unexpanded\def\tightvtop{\dowithnextbox{\ht\nextbox\zeropoint\box\nextbox}\vtop} diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf Binary files differindex 275625528..30d18d29b 100644 --- a/tex/context/base/context-version.pdf +++ b/tex/context/base/context-version.pdf diff --git a/tex/context/base/context-version.png b/tex/context/base/context-version.png Binary files differindex 39c348e48..67edf8a53 100644 --- a/tex/context/base/context-version.png +++ b/tex/context/base/context-version.png diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv index 8c67fbd50..0214c2bfa 100644 --- a/tex/context/base/context.mkiv +++ b/tex/context/base/context.mkiv @@ -28,8 +28,8 @@ %D up and the dependencies are more consistent. \edef\contextformat {\jobname} -\edef\contextversion{2014.02.14 17:07} -\edef\contextkind {beta} +\edef\contextversion{2014.01.03 00:40} +\edef\contextkind {current} %D For those who want to use this: @@ -143,6 +143,7 @@ \loadmarkfile{node-fin} \loadmarkfile{node-mig} +\loadmarkfile{typo-bld} % par builders %loadmarkfile{node-pag} \loadmarkfile{back-ini} @@ -170,7 +171,6 @@ %loadmarkfile{supp-num} % obsolete \loadmarkfile{typo-ini} -\loadmarkfile{typo-bld} % par builders \loadmkvifile{file-syn} \loadmkvifile{file-mod} @@ -357,7 +357,6 @@ \loadmkvifile{font-sel} \loadmarkfile{typo-tal} -\loadmarkfile{typo-par} % par builders (uses fonts) \loadmarkfile{tabl-com} \loadmarkfile{tabl-pln} @@ -402,7 +401,7 @@ \loadmarkfile{scrp-ini} \loadmarkfile{lang-wrd} % can be optional (discussion with mm sideeffect) -\loadmarkfile{lang-rep} % can be optional (bt 2013 side effect) +%loadmarkfile{lang-rep} % can be optional (bt 2013 side effect) \loadmarkfile{prop-ini} % only for downward compatibility @@ -477,17 +476,8 @@ \loadmarkfile{lang-spa} % will become obsolete -% old bibtex support: (will be m-oldbibtex.mkiv) - -% \loadmarkfile{bibl-bib} -% \loadmarkfile{bibl-tra} - -% new bibtex support: - -\loadmarkfile{publ-ini} -\loadmarkfile{publ-tra} -\loadmarkfile{publ-xml} -\loadmarkfile{publ-old} +\loadmarkfile{bibl-bib} +\loadmarkfile{bibl-tra} %loadmarkfile{x-xtag} % no longer preloaded diff --git a/tex/context/base/core-env.lua b/tex/context/base/core-env.lua index 2cc84299b..a4d1fdd92 100644 --- a/tex/context/base/core-env.lua +++ b/tex/context/base/core-env.lua @@ -31,7 +31,6 @@ tex.systemmodes = allocate { } tex.constants = allocate { } tex.conditionals = allocate { } tex.ifs = allocate { } -tex.isdefined = allocate { } local modes = { } local systemmodes = { } @@ -79,19 +78,6 @@ setmetatableindex(tex.ifs, function(t,k) return csname_id(k) ~= undefined and create(k)[2] == iftrue -- inefficient, this create, we need a helper end) -setmetatableindex(tex.isdefined, function(t,k) - return csname_id(k) ~= undefined -end) - -function context.setconditional(name,value) - if value then - context.settruevalue(name) - else - context.setfalsevalue(name) - end -end - - -- todo : global -- not possible as we let at the tex end to zerocount and plusone diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv index c07722f56..8f56b6f16 100644 --- a/tex/context/base/core-sys.mkiv +++ b/tex/context/base/core-sys.mkiv @@ -89,8 +89,6 @@ % \ctxcommand{updatefilenames("\jobame","\inputfilename","\outputfilename")}% % \to \everysetupsystem -\newconditional\prerollrun % when true it means that we have a forced number of runs - % Some mechanisms (see x-res-01) use either \jobfilename or % \jobfilename.somesuffix, in which case we need to use the % full name if given or a default (like \jobfilename.xml); diff --git a/tex/context/base/core-two.lua b/tex/context/base/core-two.lua index 1f2bc7c6c..d6e006e04 100644 --- a/tex/context/base/core-two.lua +++ b/tex/context/base/core-two.lua @@ -54,7 +54,7 @@ end function jobpasses.getdata(id,index,default) local jti = collected[id] - local value = jti and jti[index] + local value = jit and jti[index] return value ~= "" and value or default or "" end diff --git a/tex/context/base/core-uti.lua b/tex/context/base/core-uti.lua index 71b80170c..ef792c1d8 100644 --- a/tex/context/base/core-uti.lua +++ b/tex/context/base/core-uti.lua @@ -126,10 +126,6 @@ function jobvariables.save(cs,value) tobesaved[cs] = value end -function jobvariables.restore(cs) - return collected[cs] or tobesaved[cs] -end - -- checksums function jobvariables.getchecksum(tag) @@ -327,7 +323,7 @@ if jit then local saved = watts_per_core * runtime * kg_per_watt_per_second / speedup_by_other_engine local saved = used_wood_factor * runtime -- return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second, %f kg tree saved by using luajittex",runtime,pages,shipped,persecond,saved) - return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second, %f mg tree saved by using luajittex",runtime,pages,shipped,persecond,saved*1000*1000) + return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second, %f g tree saved by using luajittex",runtime,pages,shipped,persecond,saved*1000) else return format("%s seconds, %i processed pages, %i shipped pages, %.3f pages/second",runtime,pages,shipped,persecond) end diff --git a/tex/context/base/data-aux.lua b/tex/context/base/data-aux.lua index dae96ce62..b969e6070 100644 --- a/tex/context/base/data-aux.lua +++ b/tex/context/base/data-aux.lua @@ -16,8 +16,7 @@ local resolvers = resolvers local report_scripts = logs.reporter("resolvers","scripts") function resolvers.updatescript(oldname,newname) -- oldname -> own.name, not per se a suffix - -- local scriptpath = "scripts/context/lua" - local scriptpath = "context/lua" + local scriptpath = "scripts/context/lua" newname = file.addsuffix(newname,"lua") local oldscript = resolvers.cleanpath(oldname) if trace_locating then diff --git a/tex/context/base/data-use.lua b/tex/context/base/data-use.lua index 7598506e4..9c15263bb 100644 --- a/tex/context/base/data-use.lua +++ b/tex/context/base/data-use.lua @@ -57,7 +57,7 @@ statistics.register("used cache path", function() return caches.usedpaths() end -- experiment (code will move) function statistics.savefmtstatus(texname,formatbanner,sourcefile) -- texname == formatname - local enginebanner = status.banner + local enginebanner = status.list().banner if formatbanner and enginebanner and sourcefile then local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv local luvdata = { @@ -75,7 +75,7 @@ end -- a remake function statistics.checkfmtstatus(texname) - local enginebanner = status.banner + local enginebanner = status.list().banner if enginebanner and texname then local luvname = file.replacesuffix(texname,"luv") -- utilities.lua.suffixes.luv if lfs.isfile(luvname) then diff --git a/tex/context/base/enco-ini.mkiv b/tex/context/base/enco-ini.mkiv index ab3aa488d..77fcbe483 100644 --- a/tex/context/base/enco-ini.mkiv +++ b/tex/context/base/enco-ini.mkiv @@ -87,26 +87,17 @@ %D Accent handling (try to avoid this): -% \buildtextaccent\greekdasia\greekalphamacron -% \buildtextaccent\textacute q - \newbox\b_enco_accent \def\buildmathaccent#1% {\mathaccent#1 } -% \unexpanded\def\buildtextaccent#1#2% we could do all at the lua end -% {\begingroup % but that's no fun (yet) -% \setbox\b_enco_accent\hbox{#1}% -% \scratchcounter\cldcontext{nodes.firstcharinbox(\number\b_enco_accent)}\relax -% \ifcase\scratchcounter\else\accent\scratchcounter\fi -% \relax#2% -% \endgroup} - \unexpanded\def\buildtextaccent#1#2% we could do all at the lua end {\begingroup % but that's no fun (yet) \setbox\b_enco_accent\hbox{#1}% - \ctxcommand{buildtextaccent(\number\b_enco_accent)}#2% + \scratchcounter\cldcontext{nodes.firstcharinbox(\number\b_enco_accent)}\relax + \ifcase\scratchcounter\else\accent\scratchcounter\fi + \relax#2% \endgroup} \unexpanded\def\bottomaccent#1#2#3#4#5% down right slantcorrection accent char diff --git a/tex/context/base/export-example.css b/tex/context/base/export-example.css index dbecc01fe..06d51c587 100644 --- a/tex/context/base/export-example.css +++ b/tex/context/base/export-example.css @@ -709,18 +709,3 @@ a[href]:hover { color : rgb(50%,0%,0%) ; text-decoration : underline ; } - -/* setups */ - -setup { - display : block ; -} - -comment { - background-color : rgb(50%,75%,100%) ; - display : block ; - padding : 1em ; - margin-bottom : 1em ; - margin-top : 1em ; - font-family : "Lucida Console", "DejaVu Sans Mono", monospace ; -} diff --git a/tex/context/base/file-job.lua b/tex/context/base/file-job.lua index c88eb7e9d..288a690d2 100644 --- a/tex/context/base/file-job.lua +++ b/tex/context/base/file-job.lua @@ -801,45 +801,23 @@ function commands.getcommandline() -- has to happen at the tex end in order to e inputfile = basename(inputfile) end - local forcedruns = arguments.forcedruns local kindofrun = arguments.kindofrun - local currentrun = arguments.currentrun - local maxnofruns = arguments.maxnofruns or arguments.runs - - -- context.setupsystem { - -- [constants.directory] = validstring(arguments.setuppath), - -- [constants.inputfile] = inputfile, - -- [constants.file] = validstring(arguments.result), - -- [constants.random] = validstring(arguments.randomseed), - -- -- old: - -- [constants.n] = validstring(kindofrun), - -- [constants.m] = validstring(currentrun), - -- } + local currentrun = arguments.maxnofruns + local maxnofruns = arguments.currentrun context.setupsystem { - directory = validstring(arguments.setuppath), - inputfile = inputfile, - file = validstring(arguments.result), - random = validstring(arguments.randomseed), + [constants.directory] = validstring(arguments.setuppath), + [constants.inputfile] = inputfile, + [constants.file] = validstring(arguments.result), + [constants.random] = validstring(arguments.randomseed), -- old: - n = validstring(kindofrun), - m = validstring(currentrun), + [constants.n] = validstring(kindofrun), + [constants.m] = validstring(currentrun), } - forcedruns = tonumber(forcedruns) or 0 - kindofrun = tonumber(kindofrun) or 0 - maxnofruns = tonumber(maxnofruns) or 0 - currentrun = tonumber(currentrun) or 0 - - local prerollrun = forcedruns > 0 and currentrun > 0 and currentrun < forcedruns - - environment.forcedruns = forcedruns - environment.kindofrun = kindofrun - environment.maxnofruns = maxnofruns - environment.currentrun = currentrun - environment.prerollrun = prerollrun - - context.setconditional("prerollrun",prerollrun) + environment.kindofrun = tonumber(kindofrun) or 0 + environment.maxnofruns = tonumber(maxnofruns) or 0 + environment.currentrun = tonumber(currentrun) or 0 if validstring(arguments.arguments) then context.setupenv { arguments.arguments } diff --git a/tex/context/base/file-job.mkvi b/tex/context/base/file-job.mkvi index fa395a32e..ce0d54ece 100644 --- a/tex/context/base/file-job.mkvi +++ b/tex/context/base/file-job.mkvi @@ -274,7 +274,7 @@ %D Relatively new (might move as it depends on setups): -%newtoks\everysetupdocument +\newtoks\everysetupdocument \unexpanded\def\startdocument % todo: dostarttagged\t!document {\dosingleargument\syst_structure_document_start} diff --git a/tex/context/base/file-res.lua b/tex/context/base/file-res.lua index 8a50c0d58..8e65ba4c7 100644 --- a/tex/context/base/file-res.lua +++ b/tex/context/base/file-res.lua @@ -6,14 +6,13 @@ if not modules then modules = { } end modules ['file-res'] = { license = "see context related readme files" } -local format, find = string.format, string.find +local format = string.format local isfile = lfs.isfile local is_qualified_path = file.is_qualified_path -local hasscheme, urlescape = url.hasscheme, url.escape +local hasscheme = url.hasscheme -local trace_files = false trackers.register("resolvers.readfile", function(v) trace_files = v end) -local trace_details = false trackers.register("resolvers.readfile.details", function(v) trace_details = v end) -local report_files = logs.reporter("files","readfile") +local trace_files = false trackers.register("resolvers.readfile", function(v) trace_files = v end) +local report_files = logs.reporter("files","readfile") resolvers.maxreadlevel = 2 @@ -24,9 +23,6 @@ local finders, loaders, openers = resolvers.finders, resolvers.loaders, resolver local found = { } -- can best be done in the resolver itself local function readfilename(specification,backtrack,treetoo) - if trace_details then - report_files(table.serialize(specification,"specification")) - end local name = specification.filename local fnd = name and found[name] if not fnd then @@ -136,11 +132,9 @@ function getreadfilename(scheme,path,name) -- better do a split and then pass ta if hasscheme(name) or is_qualified_path(name) then fullname = name else - if not find(name,"%%") then - name = urlescape(name) -- if no % in names - end fullname = ((path == "") and format("%s:///%s",scheme,name)) or format("%s:///%s/%s",scheme,path,name) end +--~ print(">>>",fullname) return resolvers.findtexfile(fullname) or "" -- can be more direct end diff --git a/tex/context/base/font-chk.lua b/tex/context/base/font-chk.lua index 5d4f6059b..6dc1667bb 100644 --- a/tex/context/base/font-chk.lua +++ b/tex/context/base/font-chk.lua @@ -41,18 +41,9 @@ local enableaction = tasks.enableaction local disableaction = tasks.disableaction local glyph_code = nodes.nodecodes.glyph - -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getfont = nuts.getfont -local getchar = nuts.getchar -local setfield = nuts.setfield - -local traverse_id = nuts.traverse_id -local remove_node = nuts.remove -local insert_node_after = nuts.insert_after +local traverse_id = node.traverse_id +local remove_node = nodes.remove +local insert_node_after = node.insert_after -- maybe in fonts namespace -- deletion can be option @@ -214,10 +205,9 @@ end function checkers.missing(head) local lastfont, characters, found = nil, nil, nil - head = tonut(head) for n in traverse_id(glyph_code,head) do -- faster than while loop so we delay removal - local font = getfont(n) - local char = getchar(n) + local font = n.font + local char = n.char if font ~= lastfont then characters = fontcharacters[font] lastfont = font @@ -246,8 +236,8 @@ function checkers.missing(head) elseif action == "replace" then for i=1,#found do local n = found[i] - local font = getfont(n) - local char = getchar(n) + local font = n.font + local char = n.char local tfmdata = fontdata[font] local properties = tfmdata.properties local privates = properties.privates @@ -265,13 +255,13 @@ function checkers.missing(head) head = remove_node(head,n,true) else -- good, we have \definefontfeature[default][default][missing=yes] - setfield(n,"char",p) + n.char = p end end else -- maye write a report to the log end - return tonode(head), false + return head, false end local relevant = { "missing (will be deleted)", "missing (will be flagged)", "missing" } diff --git a/tex/context/base/font-col.lua b/tex/context/base/font-col.lua index 187e33311..f5e17f1da 100644 --- a/tex/context/base/font-col.lua +++ b/tex/context/base/font-col.lua @@ -17,12 +17,7 @@ local type, next, toboolean = type, next, toboolean local gmatch = string.gmatch local fastcopy = table.fastcopy -local nuts = nodes.nuts -local tonut = nuts.tonut -local getfont = nuts.getfont -local getchar = nuts.getchar -local setfield = nuts.setfield -local traverse_id = nuts.traverse_id +local traverse_id = nodes.traverse_id local settings_to_hash = utilities.parsers.settings_to_hash @@ -204,7 +199,7 @@ end -- -- if lpegmatch(okay,name) then -function collections.prepare(name) -- we can do this in lua now .. todo +function collections.prepare(name) -- we can do this in lua now current = currentfont() if vectors[current] then return @@ -249,23 +244,23 @@ end function collections.process(head) -- this way we keep feature processing local done = false - for n in traverse_id(glyph_code,tonut(head)) do - local v = vectors[getfont(n)] + for n in traverse_id(glyph_code,head) do + local v = vectors[n.font] if v then - local id = v[getchar(n)] + local id = v[n.char] if id then if type(id) == "table" then local newid, newchar = id[1], id[2] if trace_collecting then report_fonts("remapping character %C in font %a to character %C in font %a",getchar(n),getfont(n),newchar,newid) end - setfield(n,"font",newid) - setfield(n,"char",newchar) + n.font = newid + n.char = newchar else if trace_collecting then report_fonts("remapping font %a to %a for character %C",getfont(n),id,getchar(n)) end - setfield(n,"font",id) + n.font = id end end end diff --git a/tex/context/base/font-ctx.lua b/tex/context/base/font-ctx.lua index e251cc9c1..b08a6aed2 100644 --- a/tex/context/base/font-ctx.lua +++ b/tex/context/base/font-ctx.lua @@ -57,16 +57,6 @@ local helpers = fonts.helpers local hashes = fonts.hashes local currentfont = font.current -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getattr = nuts.getattr -local getfont = nuts.getfont - -local setfield = nuts.setfield -local setattr = nuts.setattr - local texgetattribute = tex.getattribute local texsetattribute = tex.setattribute local texgetdimen = tex.getdimen @@ -137,8 +127,8 @@ function fonts.helpers.name(tfmdata) return file.basename(type(tfmdata) == "number" and properties[tfmdata].name or tfmdata.properties.name) end -utilities.strings.formatters.add(formatters,"font:name", [["'"..fontname(%s).."'"]], { fontname = fonts.helpers.name }) -utilities.strings.formatters.add(formatters,"font:features",[["'"..sequenced(%s," ",true).."'"]], { sequenced = table.sequenced }) +utilities.strings.formatters.add(formatters,"font:name", [["'"..fonts.helpers.name(%s).."'"]]) +utilities.strings.formatters.add(formatters,"font:features",[["'"..table.sequenced(%s," ",true).."'"]]) -- ... like font-sfm or so @@ -1911,25 +1901,24 @@ end -- a fontkern plug: +local copy_node = node.copy +local kern = nodes.pool.register(nodes.pool.kern()) -local copy_node = nuts.copy -local kern = nuts.pool.register(nuts.pool.kern()) - -setattr(kern,attributes.private('fontkern'),1) -- we can have several, attributes are shared +node.set_attribute(kern,attributes.private('fontkern'),1) -- we can have several, attributes are shared nodes.injections.installnewkern(function(k) local c = copy_node(kern) - setfield(c,"kern",k) + c.kern = k return c end) -directives.register("nodes.injections.fontkern", function(v) setfield(kern,"subtype",v and 0 or 1) end) +directives.register("nodes.injections.fontkern", function(v) kern.subtype = v and 0 or 1 end) -- here local trace_analyzing = false trackers.register("otf.analyzing", function(v) trace_analyzing = v end) -local otffeatures = constructors.newfeatures("otf") +local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register local analyzers = fonts.analyzers @@ -1937,7 +1926,7 @@ local methods = analyzers.methods local unsetvalue = attributes.unsetvalue -local traverse_by_id = nuts.traverse_id +local traverse_by_id = node.traverse_id local a_color = attributes.private('color') local a_colormodel = attributes.private('colormodel') @@ -1964,17 +1953,16 @@ local names = { local function markstates(head) if head then - head = tonut(head) - local model = getattr(head,a_colormodel) or 1 + local model = head[a_colormodel] or 1 for glyph in traverse_by_id(glyph_code,head) do - local a = getattr(glyph,a_state) + local a = glyph[a_state] if a then local name = names[a] if name then local color = m_color[name] if color then - setattr(glyph,a_colormodel,model) - setattr(glyph,a_color,color) + glyph[a_colormodel] = model + glyph[a_color] = color end end end @@ -2017,8 +2005,8 @@ registerotffeature { -- adapts function methods.nocolor(head,font,attr) for n in traverse_by_id(glyph_code,head) do - if not font or getfont(n) == font then - setattr(n,a_color,unsetvalue) + if not font or n.font == font then + n[a_color] = unsetvalue end end return head, true diff --git a/tex/context/base/font-gds.lua b/tex/context/base/font-gds.lua index e57f784a0..7131ecad5 100644 --- a/tex/context/base/font-gds.lua +++ b/tex/context/base/font-gds.lua @@ -46,12 +46,7 @@ local findfile = resolvers.findfile local glyph_code = nodes.nodecodes.glyph -local nuts = nodes.nuts -local tonut = nuts.tonut -local getfont = nuts.getfont -local getchar = nuts.getchar -local getattr = nuts.getattr -local traverse_id = nuts.traverse_id +local traverse_id = nodes.traverse_id function fontgoodies.report(what,trace,goodies) if trace_goodies or trace then @@ -316,16 +311,16 @@ local setnodecolor = nodes.tracers.colors.set -- function colorschemes.coloring(head) -- local lastfont, lastscheme -- local done = false --- for n in traverse_id(glyph_code,tonut(head)) do --- local a = getattr(n,a_colorscheme) +-- for n in traverse_id(glyph_code,head) do +-- local a = n[a_colorscheme] -- if a then --- local f = getfont(n) +-- local f = n.font -- if f ~= lastfont then -- lastscheme = fontproperties[f].colorscheme -- lastfont = f -- end -- if lastscheme then --- local sc = lastscheme[getchar(n)] +-- local sc = lastscheme[n.char] -- if sc then -- done = true -- setnodecolor(n,"colorscheme:"..a..":"..sc) -- slow @@ -343,21 +338,21 @@ local setnodecolor = nodes.tracers.colors.set -- local lastattr = nil -- local lastscheme = nil -- local lastprefix = nil --- local done = nil --- for n in traverse_id(glyph_code,tonut(head)) do --- local a = getattr(n,a_colorscheme) +-- local done = nil +-- for n in traverse_id(glyph_code,head) do +-- local a = n[a_colorscheme] -- if a then -- if a ~= lastattr then -- lastattr = a -- lastprefix = "colorscheme:" .. a .. ":" -- end --- local f = getfont(n) +-- local f = n.font -- if f ~= lastfont then -- lastfont = f -- lastscheme = fontproperties[f].colorscheme -- end -- if lastscheme then --- local sc = lastscheme[getchar(n)] +-- local sc = lastscheme[n.char] -- if sc then -- setnodecolor(n,lastprefix .. sc) -- slow -- done = true @@ -389,10 +384,10 @@ function colorschemes.coloring(head) local lastcache = nil local lastscheme = nil local done = nil - for n in traverse_id(glyph_code,tonut(head)) do - local a = getattr(n,a_colorscheme) + for n in traverse_id(glyph_code,head) do + local a = n[a_colorscheme] if a then - local f = getfont(n) + local f = n.font if f ~= lastfont then lastfont = f lastscheme = fontproperties[f].colorscheme @@ -402,7 +397,7 @@ function colorschemes.coloring(head) lastcache = cache[a] end if lastscheme then - local sc = lastscheme[getchar(n)] + local sc = lastscheme[n.char] if sc then setnodecolor(n,lastcache[sc]) -- we could inline this one done = true diff --git a/tex/context/base/font-map.lua b/tex/context/base/font-map.lua index f74e13e81..ce724b973 100644 --- a/tex/context/base/font-map.lua +++ b/tex/context/base/font-map.lua @@ -66,6 +66,21 @@ local function makenameparser(str) end end +-- local parser = makenameparser("Japan1") +-- local parser = makenameparser() +-- local function test(str) +-- local b, a = lpegmatch(parser,str) +-- print((a and table.serialize(b)) or b) +-- end +-- test("a.sc") +-- test("a") +-- test("uni1234") +-- test("uni1234.xx") +-- test("uni12349876") +-- test("u123400987600") +-- test("index1234") +-- test("Japan1.123") + local function tounicode16(unicode,name) if unicode < 0x10000 then return format("%04X",unicode) @@ -331,18 +346,3 @@ function mappings.addtounicode(data,filename) report_fonts("%s tounicode entries added, ligatures %s",nl+ns,ns) end end - --- local parser = makenameparser("Japan1") --- local parser = makenameparser() --- local function test(str) --- local b, a = lpegmatch(parser,str) --- print((a and table.serialize(b)) or b) --- end --- test("a.sc") --- test("a") --- test("uni1234") --- test("uni1234.xx") --- test("uni12349876") --- test("u123400987600") --- test("index1234") --- test("Japan1.123") diff --git a/tex/context/base/font-mis.lua b/tex/context/base/font-mis.lua index 63cae37f3..e1d1ebeb9 100644 --- a/tex/context/base/font-mis.lua +++ b/tex/context/base/font-mis.lua @@ -22,7 +22,7 @@ local handlers = fonts.handlers handlers.otf = handlers.otf or { } local otf = handlers.otf -otf.version = otf.version or 2.751 +otf.version = otf.version or 2.749 otf.cache = otf.cache or containers.define("fonts", "otf", otf.version, true) function otf.loadcached(filename,format,sub) diff --git a/tex/context/base/font-nod.lua b/tex/context/base/font-nod.lua index 8251dc588..7fa3297d4 100644 --- a/tex/context/base/font-nod.lua +++ b/tex/context/base/font-nod.lua @@ -41,6 +41,13 @@ tracers.characters = char_tracers local step_tracers = tracers.steppers or { } tracers.steppers = step_tracers +local texsetbox = tex.setbox + +local copy_node_list = nodes.copy_list +local hpack_node_list = nodes.hpack +local free_node_list = nodes.flush_list +local traverse_nodes = nodes.traverse + local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -52,32 +59,12 @@ local glue_code = nodecodes.glue local kern_code = nodecodes.kern local rule_code = nodecodes.rule local whatsit_code = nodecodes.whatsit +local spec_code = nodecodes.glue_spec local localpar_code = whatcodes.localpar local dir_code = whatcodes.dir -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getlist = nuts.getlist -local setbox = nuts.setbox - -local copy_node_list = nuts.copy_list -local hpack_node_list = nuts.hpack -local free_node_list = nuts.flush_list -local traverse_nodes = nuts.traverse -local protect_glyphs = nuts.protect_glyphs - -local nodepool = nuts.pool +local nodepool = nodes.pool local new_glyph = nodepool.glyph local formatters = string.formatters @@ -92,17 +79,16 @@ local fontproperties = hashes.properties local fontparameters = hashes.parameters function char_tracers.collect(head,list,tag,n) - head = tonut(head) n = n or 0 local ok, fn = false, nil while head do - local id = getid(head) + local id = head.id if id == glyph_code then - local f = getfont(head) + local f = head.font if f ~= fn then ok, fn = false, f end - local c = getchar(head) + local c = head.char local i = fontidentifiers[f].indices[c] or 0 if not ok then ok = true @@ -117,7 +103,7 @@ function char_tracers.collect(head,list,tag,n) else ok = false end - head = getnext(head) + head = head.next end end @@ -176,12 +162,12 @@ function char_tracers.indices(t,decimal) end function char_tracers.start() - local npc = handlers.characters -- should accept nuts too + local npc = handlers.characters local list = { } function handlers.characters(head) local n = #list char_tracers.collect(head,list,'before',n) - local h, d = npc(tonode(head)) -- for the moment tonode + local h, d = npc(head) char_tracers.collect(head,list,'after',n) if #list > n then list[#list+1] = { } @@ -248,8 +234,8 @@ end function step_tracers.glyphs(n,i) local c = collection[i] if c then - local b = hpack_node_list(copy_node_list(c)) -- multiple arguments - setbox(n,b) + local b = hpack_node_list(copy_node_list(c)) -- multiple arguments + texsetbox(n,b) end end @@ -257,8 +243,8 @@ function step_tracers.features() -- we cannot use first_glyph here as it only finds characters with subtype < 256 local f = collection[1] while f do - if getid(f) == glyph_code then - local tfmdata, t = fontidentifiers[getfont(f)], { } + if f.id == glyph_code then + local tfmdata, t = fontidentifiers[f.font], { } for feature, value in table.sortedhash(tfmdata.shared.features) do if feature == "number" or feature == "features" then -- private @@ -279,24 +265,22 @@ function step_tracers.features() end return end - f = getnext(f) + f = f.next end end function tracers.fontchar(font,char) local n = new_glyph() - setfield(n,"font",font) - setfield(n,"char",char) - setfield(n,"subtype",256) - context(tonode(n)) + n.font, n.char, n.subtype = font, char, 256 + context(n) end function step_tracers.font(command) local c = collection[1] while c do - local id = getid(c) + local id = c.id if id == glyph_code then - local font = getfont(c) + local font = c.font local name = file.basename(fontproperties[font].filename or "unknown") local size = fontparameters[font].size or 0 if command then @@ -306,7 +290,7 @@ function step_tracers.font(command) end return else - c = getnext(c) + c = c.next end end end @@ -314,22 +298,22 @@ end function step_tracers.codes(i,command) local c = collection[i] while c do - local id = getid(c) + local id = c.id if id == glyph_code then if command then - local f, c = getfont(c), getchar(c) + local f, c = c.font,c.char local d = fontdescriptions[f] local d = d and d[c] context[command](f,c,d and d.class or "") else - context("[%s:U+%04X]",getfont(c),getchar(c)) + context("[%s:U+%04X]",c.font,c.char) end - elseif id == whatsit_code and (getsubtype(c) == localpar_code or getsubtype(c) == dir_code) then - context("[%s]",getfield(c,"dir")) + elseif id == whatsit_code and (c.subtype == localpar_code or c.subtype == dir_code) then + context("[%s]",c.dir) else context("[%s]",nodecodes[id]) end - c = getnext(c) + c = c.next end end @@ -355,10 +339,9 @@ end function step_tracers.check(head) if collecting then step_tracers.reset() - local n = copy_node_list(tonut(head)) + local n = copy_node_list(head) injections.handler(n,nil,"trace",true) - -- handlers.protectglyphs(n) -- can be option - protect_glyphs(n) + handlers.protectglyphs(n) -- can be option collection[1] = n end end @@ -367,10 +350,9 @@ function step_tracers.register(head) if collecting then local nc = #collection+1 if messages[nc] then - local n = copy_node_list(tonut(head)) + local n = copy_node_list(head) injections.handler(n,nil,"trace",true) - -- handlers.protectglyphs(n) -- can be option - protect_glyphs(n) + handlers.protectglyphs(n) -- can be option collection[nc] = n end end @@ -393,28 +375,21 @@ local threshold = 65536 local function toutf(list,result,nofresult,stopcriterium) if list then - for n in traverse_nodes(tonut(list)) do - local id = getid(n) + for n in traverse_nodes(list) do + local id = n.id if id == glyph_code then - local components = getfield(n,"components") + local components = n.components if components then result, nofresult = toutf(components,result,nofresult) else - local c = getchar(n) - local fc = fontcharacters[getfont(n)] + local c = n.char + local fc = fontcharacters[n.font] if fc then - local fcc = fc[c] - if fcc then - -- == fromunicode - local u = fcc.tounicode - if u then - for s in gmatch(u,"....") do - nofresult = nofresult + 1 - result[nofresult] = utfchar(tonumber(s,16)) - end - else + local u = fc[c].tounicode + if u then + for s in gmatch(u,"....") do nofresult = nofresult + 1 - result[nofresult] = utfchar(c) + result[nofresult] = utfchar(tonumber(s,16)) end else nofresult = nofresult + 1 @@ -422,23 +397,23 @@ local function toutf(list,result,nofresult,stopcriterium) end else nofresult = nofresult + 1 - result[nofresult] = f_unicode(c) + result[nofresult] = utfchar(c) end end elseif id == disc_code then - result, nofresult = toutf(getfield(n,"replace"),result,nofresult) -- needed? + result, nofresult = toutf(n.replace,result,nofresult) -- needed? elseif id == hlist_code or id == vlist_code then -- if nofresult > 0 and result[nofresult] ~= " " then -- nofresult = nofresult + 1 -- result[nofresult] = " " -- end - result, nofresult = toutf(getlist(n),result,nofresult) + result, nofresult = toutf(n.list,result,nofresult) elseif id == glue_code then if nofresult > 0 and result[nofresult] ~= " " then nofresult = nofresult + 1 result[nofresult] = " " end - elseif id == kern_code and getfield(n,"kern") > threshold then + elseif id == kern_code and n.kern > threshold then if nofresult > 0 and result[nofresult] ~= " " then nofresult = nofresult + 1 result[nofresult] = " " diff --git a/tex/context/base/font-odv.lua b/tex/context/base/font-odv.lua index d07c38d9a..69f74dfa5 100644 --- a/tex/context/base/font-odv.lua +++ b/tex/context/base/font-odv.lua @@ -15,9 +15,6 @@ if not modules then modules = { } end modules ['font-odv'] = { -- deva: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/introO.mspx -- dev2: http://www.microsoft.com/typography/OpenType%20Dev/devanagari/intro.mspx -- --- Rajeesh Nambiar provided patches for the malayalam variant. Thansk to feedback from --- the mailing list some aspects could be improved. --- -- As I touched nearly all code, reshuffled it, optimized a lot, etc. etc. (imagine how -- much can get messed up in over a week work) it could be that I introduced bugs. There -- is more to gain (esp in the functions applied to a range) but I'll do that when @@ -50,10 +47,7 @@ if not modules then modules = { } end modules ['font-odv'] = { -- Some data will move to char-def.lua (some day). -- -- Hans Hagen, PRAGMA-ADE, Hasselt NL --- --- We could have c_nukta, c_halant, c_ra is we know that they are never used mixed within --- one script .. yes or no? --- + -- Matras: according to Microsoft typography specifications "up to one of each type: -- pre-, above-, below- or post- base", but that does not seem to be right. It could -- become an option. @@ -63,9 +57,9 @@ if not modules then modules = { } end modules ['font-odv'] = { -- -- local function ms_matra(c) -- local prebase, abovebase, belowbase, postbase = true, true, true, true --- local n = getnext(c) --- while n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font do --- local char = getchar(n) +-- local n = c.next +-- while n and n.id == glyph_code and n.subtype < 256 and n.font == font do +-- local char = n.char -- if not dependent_vowel[char] then -- break -- elseif pre_mark[char] and prebase then @@ -79,7 +73,7 @@ if not modules then modules = { } end modules ['font-odv'] = { -- else -- return c -- end --- c = getnext(c) +-- c = c.next -- end -- return c -- end @@ -106,26 +100,11 @@ local methods = fonts.analyzers.methods local otffeatures = fonts.constructors.newfeatures("otf") local registerotffeature = otffeatures.register -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getchar = nuts.getchar -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getfield = nuts.getfield -local setfield = nuts.setfield -local getattr = nuts.getattr -local setattr = nuts.setattr - -local insert_node_after = nuts.insert_after -local copy_node = nuts.copy -local free_node = nuts.free -local remove_node = nuts.remove -local flush_list = nuts.flush_list +local insert_node_after = nodes.insert_after +local copy_node = nodes.copy +local free_node = nodes.free +local remove_node = nodes.remove +local flush_list = nodes.flush_list local unsetvalue = attributes.unsetvalue @@ -162,7 +141,7 @@ xprocesscharacters = function(head,font) end local function processcharacters(head,font) - return tonut(xprocesscharacters(tonode(head))) + return xprocesscharacters(head) end -- function processcharacters(head,font) @@ -177,10 +156,6 @@ end -- Gurmukhi, Kannada, Malayalam, Oriya, Tamil, Telugu. Feel free to provide the -- code points. --- We can assume that script are not mixed in the source but if that is the case --- we might need to have consonants etc per script and initialize a local table --- pointing to the right one. - local consonant = { -- devanagari [0x0915] = true, [0x0916] = true, [0x0917] = true, [0x0918] = true, @@ -207,17 +182,6 @@ local consonant = { [0x0CB5] = true, [0x0CB6] = true, [0x0CB7] = true, [0x0CB8] = true, [0x0CB9] = true, [0x0CDE] = true, -- obsolete - -- malayalam - [0x0D15] = true, [0x0D16] = true, [0x0D17] = true, [0x0D18] = true, - [0x0D19] = true, [0x0D1A] = true, [0x0D1B] = true, [0x0D1C] = true, - [0x0D1D] = true, [0x0D1E] = true, [0x0D1F] = true, [0x0D20] = true, - [0x0D21] = true, [0x0D22] = true, [0x0D23] = true, [0x0D24] = true, - [0x0D25] = true, [0x0D26] = true, [0x0D27] = true, [0x0D28] = true, - [0x0D29] = true, [0x0D2A] = true, [0x0D2B] = true, [0x0D2C] = true, - [0x0D2D] = true, [0x0D2E] = true, [0x0D2F] = true, [0x0D30] = true, - [0x0D31] = true, [0x0D32] = true, [0x0D33] = true, [0x0D34] = true, - [0x0D35] = true, [0x0D36] = true, [0x0D37] = true, [0x0D38] = true, - [0x0D39] = true, [0x0D3A] = true, } local independent_vowel = { @@ -234,11 +198,6 @@ local independent_vowel = { [0x0C89] = true, [0x0C8A] = true, [0x0C8B] = true, [0x0C8C] = true, [0x0C8D] = true, [0x0C8E] = true, [0x0C8F] = true, [0x0C90] = true, [0x0C91] = true, [0x0C92] = true, [0x0C93] = true, [0x0C94] = true, - -- malayalam - [0x0D05] = true, [0x0D06] = true, [0x0D07] = true, [0x0D08] = true, - [0x0D09] = true, [0x0D0A] = true, [0x0D0B] = true, [0x0D0C] = true, - [0x0D0E] = true, [0x0D0F] = true, [0x0D10] = true, [0x0D12] = true, - [0x0D13] = true, [0x0D14] = true, } local dependent_vowel = { -- matra @@ -254,11 +213,6 @@ local dependent_vowel = { -- matra [0x0CC2] = true, [0x0CC3] = true, [0x0CC4] = true, [0x0CC5] = true, [0x0CC6] = true, [0x0CC7] = true, [0x0CC8] = true, [0x0CC9] = true, [0x0CCA] = true, [0x0CCB] = true, [0x0CCC] = true, - -- malayalam - [0x0D3E] = true, [0x0D3F] = true, [0x0D40] = true, [0x0D41] = true, - [0x0D42] = true, [0x0D43] = true, [0x0D44] = true, [0x0D46] = true, - [0x0D47] = true, [0x0D48] = true, [0x0D4A] = true, [0x0D4B] = true, - [0x0D4C] = true, [0x0D57] = true, } local vowel_modifier = { @@ -270,16 +224,10 @@ local vowel_modifier = { [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true, [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true, [0xA8F0] = true, [0xA8F1] = true, - -- malayalam - [0x0D02] = true, [0x0D03] = true, } local stress_tone_mark = { [0x0951] = true, [0x0952] = true, [0x0953] = true, [0x0954] = true, - -- kannada - [0x0CCD] = true, - -- malayalam - [0x0D4D] = true, } local nukta = { @@ -294,19 +242,9 @@ local halant = { [0x094D] = true, -- kannada [0x0CCD] = true, - -- malayalam - [0x0D4D] = true, -} - -local ra = { - -- devanagari - [0x0930] = true, - -- kannada - [0x0CB0] = true, - -- malayalam - [0x0D30] = true, } +local c_ra = 0x0930 -- used to be tables (also used as constant) local c_anudatta = 0x0952 -- used to be tables local c_nbsp = 0x00A0 -- used to be tables local c_zwnj = 0x200C -- used to be tables @@ -332,8 +270,6 @@ local zw_char = { -- could also be inlined local pre_mark = { [0x093F] = true, [0x094E] = true, - -- malayalam - [0x0D46] = true, [0x0D47] = true, [0x0D48] = true, } local above_mark = { @@ -345,8 +281,6 @@ local above_mark = { [0xA8E8] = true, [0xA8E9] = true, [0xA8EA] = true, [0xA8EB] = true, [0xA8EC] = true, [0xA8ED] = true, [0xA8EE] = true, [0xA8EF] = true, [0xA8F0] = true, [0xA8F1] = true, - -- malayalam - [0x0D4E] = true, } local below_mark = { @@ -361,13 +295,6 @@ local post_mark = { [0x094F] = true, } -local twopart_mark = { - -- malayalam - [0x0D4A] = { 0x0D46, 0x0D3E, }, -- ൊ - [0x0D4B] = { 0x0D47, 0x0D3E, }, -- ോ - [0x0D4C] = { 0x0D46, 0x0D57, }, -- ൌ -} - local mark_four = { } -- As we access these frequently an extra hash is used. for k, v in next, pre_mark do mark_four[k] = pre_mark end @@ -419,7 +346,6 @@ local reorder_class = { [0x0CC4] = "after subscript", [0x0CD5] = "after subscript", [0x0CD6] = "after subscript", - -- malayalam } -- We use some pseudo features as we need to manipulate the nodelist based @@ -500,7 +426,7 @@ local basic_shaping_forms = { local function initializedevanagi(tfmdata) local script, language = otf.scriptandlanguage(tfmdata,attr) -- todo: take fast variant - if script == "deva" or script == "dev2" or script =="mlym" or script == "mlm2" then + if script == "deva" or script == "dev2" then local resources = tfmdata.resources local lookuphash = resources.lookuphash if not lookuphash["dv01"] then @@ -538,20 +464,15 @@ local function initializedevanagi(tfmdata) -- if script == "deva" then sharedfeatures["dv04"] = true -- dv04_remove_joiners - elseif script == "dev2" then + end + -- + if script == "dev2" then sharedfeatures["dv01"] = true -- dv01_reorder_matras sharedfeatures["dv02"] = true -- dv02_reorder_reph sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants sharedfeatures["dv04"] = true -- dv04_remove_joiners - elseif script == "mlym" then - sharedfeatures["pstf"] = true - elseif script == "mlm2" then - sharedfeatures["pstf"] = true - sharedfeatures["pref"] = true - sharedfeatures["dv03"] = true -- dv03_reorder_pre_base_reordering_consonants - gsubfeatures["dv03"] = dev2_defaults -- reorder pre base reordering consonants - insert(sequences,insertindex,sequence_reorder_pre_base_reordering_consonants) end + -- end end end @@ -633,30 +554,30 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces) local lookuphash, reph, vattu, blwfcache = deva_initialize(font,attr) -- could be inlines but ugly local current = start - local n = getnext(start) + local n = start.next local base = nil local firstcons = nil local lastcons = nil local basefound = false - if ra[getchar(start)] and halant[getchar(n)] and reph then + if start.char == c_ra and halant[n.char] and reph then -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph -- from candidates for base consonants if n == stop then return head, stop, nbspaces end - if getchar(getnext(n)) == c_zwj then + if n.next.char == c_zwj then current = start else - current = getnext(n) - setattr(start,a_state,s_rphf) + current = n.next + start[a_state] = s_rphf end end - if getchar(current) == c_nbsp then + if current.char == c_nbsp then -- Stand Alone cluster if current == stop then - stop = getprev(stop) + stop = stop.prev head = remove_node(head,current) free_node(current) return head, stop, nbspaces @@ -665,37 +586,37 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces) base = current firstcons = current lastcons = current - current = getnext(current) + current = current.next if current ~= stop then - if nukta[getchar(current)] then - current = getnext(current) + if nukta[current.char] then + current = current.next end - if getchar(current) == c_zwj then + if current.char == c_zwj then if current ~= stop then - local next = getnext(current) - if next ~= stop and halant[getchar(next)] then + local next = current.next + if next ~= stop and halant[next.char] then current = next - next = getnext(current) - local tmp = next and getnext(next) or nil -- needs checking + next = current.next + local tmp = next and next.next or nil -- needs checking local changestop = next == stop local tempcurrent = copy_node(next) local nextcurrent = copy_node(current) - setfield(tempcurrent,"next",nextcurrent) - setfield(nextcurrent,"prev",tempcurrent) - setattr(tempcurrent,a_state,s_blwf) + tempcurrent.next = nextcurrent + nextcurrent.prev = tempcurrent + tempcurrent[a_state] = s_blwf tempcurrent = processcharacters(tempcurrent,font) - setattr(tempcurrent,a_state,unsetvalue) - if getchar(next) == getchar(tempcurrent) then + tempcurrent[a_state] = unsetvalue + if next.char == tempcurrent.char then flush_list(tempcurrent) local n = copy_node(current) - setfield(current,"char",dotted_circle) + current.char = dotted_circle head = insert_node_after(head, current, n) else - setfield(current,"char",getchar(tempcurrent)) -- (assumes that result of blwf consists of one node) - local freenode = getnext(current) - setfield(current,"next",tmp) - if tmp then - setfield(tmp,"prev",current) + current.char = tempcurrent.char -- (assumes that result of blwf consists of one node) + local freenode = current.next + current.next = tmp + if tmp then + tmp.prev = current end free_node(freenode) flush_list(tempcurrent) @@ -712,82 +633,83 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces) while not basefound do -- find base consonant - if consonant[getchar(current)] then - setattr(current,a_state,s_half) + if consonant[current.char] then + current[a_state] = s_half if not firstcons then firstcons = current end lastcons = current if not base then base = current - elseif blwfcache[getchar(current)] then + elseif blwfcache[current.char] then -- consonant has below-base (or post-base) form - setattr(current,a_state,s_blwf) + current[a_state] = s_blwf else base = current end end basefound = current == stop - current = getnext(current) + current = current.next end if base ~= lastcons then -- if base consonant is not last one then move halant from base consonant to last one local np = base - local n = getnext(base) - if nukta[getchar(n)] then + local n = base.next + if nukta[n.char] then np = n - n = getnext(n) + n = n.next end - if halant[getchar(n)] then + if halant[n.char] then if lastcons ~= stop then - local ln = getnext(lastcons) - if nukta[getchar(ln)] then + local ln = lastcons.next + if nukta[ln.char] then lastcons = ln end end - -- local np = getprev(n) - local nn = getnext(n) - local ln = getnext(lastcons) -- what if lastcons is nn ? - setfield(np,"next",nn) - setfield(nn,"prev",np) - setfield(lastcons,"next",n) + -- local np = n.prev + local nn = n.next + local ln = lastcons.next -- what if lastcons is nn ? + np.next = nn + nn.prev = np + lastcons.next = n if ln then - setfield(ln,"prev",n) + ln.prev = n end - setfield(n,"next",ln) - setfield(n,"prev",lastcons) + n.next = ln + n.prev = lastcons if lastcons == stop then stop = n end end end - n = getnext(start) - if n ~= stop and ra[getchar(start)] and halant[getchar(n)] and not zw_char[getchar(getnext(n))] then + n = start.next + -- if start.char == c_ra and halant[n.char] and not (n ~= stop and zw_char[n.next.char]) then + if n ~= stop and start.char == c_ra and halant[n.char] and not zw_char[n.next.char] then -- if syllable starts with Ra + H then move this combination so that it follows either: -- the post-base 'matra' (if any) or the base consonant local matra = base if base ~= stop then - local next = getnext(base) - if dependent_vowel[getchar(next)] then + local next = base.next + if dependent_vowel[next.char] then matra = next end end -- [sp][start][n][nn] [matra|base][?] -- [matra|base][start] [n][?] [sp][nn] - local sp = getprev(start) - local nn = getnext(n) - local mn = getnext(matra) + local sp = start.prev + local nn = n.next + local mn = matra.next if sp then - setfield(sp,"next",nn) + sp.next = nn end - setfield(nn,"prev",sp) - setfield(matra,"next",start) - setfield(start,"prev",matra) - setfield(n,"next",mn) + nn.prev = sp + matra.next = start + start.prev = matra + n.next = mn if mn then - setfield(mn,"prev",n) + mn.prev = n end if head == start then head = nn @@ -800,17 +722,17 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces) local current = start while current ~= stop do - local next = getnext(current) - if next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwnj then - setattr(current,a_state,unsetvalue) + local next = current.next + if next ~= stop and halant[next.char] and next.next.char == c_zwnj then + current[a_state] = unsetvalue end current = next end - if base ~= stop and getattr(base,a_state) then - local next = getnext(base) - if halant[getchar(next)] and not (next ~= stop and getchar(getnext(next)) == c_zwj) then - setattr(base,a_state,unsetvalue) + if base ~= stop and base[a_state] then + local next = base.next + if halant[next.char] and not (next ~= stop and next.next.char == c_zwj) then + base[a_state] = unsetvalue end end @@ -820,62 +742,62 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces) -- classify consonants and 'matra' parts as pre-base, above-base (Reph), below-base or post-base, and group elements of the syllable (consonants and 'matras') according to this classification local current, allreordered, moved = start, false, { [base] = true } - local a, b, p, bn = base, base, base, getnext(base) - if base ~= stop and nukta[getchar(bn)] then + local a, b, p, bn = base, base, base, base.next + if base ~= stop and nukta[bn.char] then a, b, p = bn, bn, bn end while not allreordered do -- current is always consonant local c = current - local n = getnext(current) + local n = current.next local l = nil -- used ? if c ~= stop then - if nukta[getchar(n)] then + if nukta[n.char] then c = n - n = getnext(n) + n = n.next end if c ~= stop then - if halant[getchar(n)] then + if halant[n.char] then c = n - n = getnext(n) + n = n.next end - while c ~= stop and dependent_vowel[getchar(n)] do + while c ~= stop and dependent_vowel[n.char] do c = n - n = getnext(n) + n = n.next end if c ~= stop then - if vowel_modifier[getchar(n)] then + if vowel_modifier[n.char] then c = n - n = getnext(n) + n = n.next end - if c ~= stop and stress_tone_mark[getchar(n)] then + if c ~= stop and stress_tone_mark[n.char] then c = n - n = getnext(n) + n = n.next end end end end - local bp = getprev(firstcons) - local cn = getnext(current) - local last = getnext(c) + local bp = firstcons.prev + local cn = current.next + local last = c.next while cn ~= last do -- move pre-base matras... - if pre_mark[getchar(cn)] then + if pre_mark[cn.char] then if bp then - setfield(bp,"next",cn) + bp.next = cn end - local next = getnext(cn) - local prev = getprev(cn) + local next = cn.next + local prev = cn.prev if next then - setfield(next,"prev",prev) + next.prev = prev end - setfield(prev,"next",next) + prev.next = next if cn == stop then stop = prev end - setfield(cn,"prev",bp) - setfield(cn,"next",firstcons) - setfield(firstcons,"prev",cn) + cn.prev = bp + cn.next = firstcons + firstcons.prev = cn if firstcons == start then if head == start then head = cn @@ -884,29 +806,29 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces) end break end - cn = getnext(cn) + cn = cn.next end allreordered = c == stop - current = getnext(c) + current = c.next end if reph or vattu then local current, cns = start, nil while current ~= stop do local c = current - local n = getnext(current) - if ra[getchar(current)] and halant[getchar(n)] then + local n = current.next + if current.char == c_ra and halant[n.char] then c = n - n = getnext(n) + n = n.next local b, bn = base, base while bn ~= stop do - local next = getnext(bn) - if dependent_vowel[getchar(next)] then + local next = bn.next + if dependent_vowel[next.char] then b = next end bn = next end - if getattr(current,a_state) == s_rphf then + if current[a_state] == s_rphf then -- position Reph (Ra + H) after post-base 'matra' (if any) since these -- become marks on the 'matra', not on the base glyph if b ~= current then @@ -919,65 +841,65 @@ local function deva_reorder(head,start,stop,font,attr,nbspaces) if b == stop then stop = c end - local prev = getprev(current) + local prev = current.prev if prev then - setfield(prev,"next",n) + prev.next = n end if n then - setfield(n,"prev",prev) + n.prev = prev end - local next = getnext(b) - setfield(c,"next",next) + local next = b.next + c.next = next if next then - setfield(next,"prev",c) + next.prev = c end - setfield(c,"next",next) - setfield(b,"next",current) - setfield(current,"prev",b) + c.next = next + b.next = current + current.prev = b end - elseif cns and getnext(cns) ~= current then -- todo: optimize next + elseif cns and cns.next ~= current then -- position below-base Ra (vattu) following the consonants on which it is placed (either the base consonant or one of the pre-base consonants) - local cp, cnsn = getprev(current), getnext(cns) + local cp, cnsn = current.prev, cns.next if cp then - setfield(cp,"next",n) + cp.next = n end if n then - setfield(n,"prev",cp) + n.prev = cp end - setfield(cns,"next",current) - setfield(current,"prev",cns) - setfield(c,"next",cnsn) + cns.next = current + current.prev = cns + c.next = cnsn if cnsn then - setfield(cnsn,"prev",c) + cnsn.prev = c end if c == stop then stop = cp break end - current = getprev(n) + current = n.prev end else - local char = getchar(current) + local char = current.char if consonant[char] then cns = current - local next = getnext(cns) - if halant[getchar(next)] then + local next = cns.next + if halant[next.char] then cns = next end elseif char == c_nbsp then nbspaces = nbspaces + 1 cns = current - local next = getnext(cns) - if halant[getchar(next)] then + local next = cns.next + if halant[next.char] then cns = next end end end - current = getnext(current) + current = current.next end end - if getchar(base) == c_nbsp then + if base.char == c_nbsp then nbspaces = nbspaces - 1 head = remove_node(head,base) free_node(base) @@ -997,24 +919,24 @@ end function handlers.devanagari_reorder_matras(head,start,kind,lookupname,replacement) -- no leak local current = start -- we could cache attributes here - local startfont = getfont(start) - local startattr = getattr(start,a_syllabe) + local startfont = start.font + local startattr = start[a_syllabe] -- can be fast loop - while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font and getattr(current,a_syllabe) == startattr do - local next = getnext(current) - if halant[getchar(current)] and not getattr(current,a_state) then - if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == font and getattr(next,a_syllabe) == startattr and zw_char[getchar(next)] then + while current and current.id == glyph_code and current.subtype<256 and current.font == font and current[a_syllabe] == startattr do + local next = current.next + if halant[current.char] and not current[a_state] then + if next and next.id == glyph_code and next.subtype<256 and next.font == font and next[a_syllabe] == startattr and zw_char[next.char] then current = next end - local startnext = getnext(start) + local startnext = start.next head = remove_node(head,start) - local next = getnext(current) + local next = current.next if next then - setfield(next,"prev",start) + next.prev = start end - setfield(start,"next",next) - setfield(current,"next",start) - setfield(start,"prev",current) + start.next = next + current.next = start + start.prev = current start = startnext break end @@ -1050,98 +972,98 @@ end function handlers.devanagari_reorder_reph(head,start,kind,lookupname,replacement) -- since in Devanagari reph has reordering position 'before postscript' dev2 only follows step 2, 4, and 6, -- the other steps are still ToDo (required for scripts other than dev2) - local current = getnext(start) + local current = start.next local startnext = nil local startprev = nil - local startfont = getfont(start) - local startattr = getattr(start,a_syllabe) - while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getattr(current,a_syllabe) == startattr do --step 2 - if halant[getchar(current)] and not getattr(current,a_state) then - local next = getnext(current) - if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == startfont and getattr(next,a_syllabe) == startattr and zw_char[getchar(next)] then + local startfont = start.font + local startattr = start[a_syllabe] + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do --step 2 + if halant[current.char] and not current[a_state] then + local next = current.next + if next and next.id == glyph_code and next.subtype<256 and next.font == startfont and next[a_syllabe] == startattr and zw_char[next.char] then current = next end - startnext = getnext(start) + startnext = start.next head = remove_node(head,start) - local next = getnext(current) + local next = current.next if next then - setfield(next,"prev",start) + next.prev = start end - setfield(start,"next",next) - setfield(current,"next",start) - setfield(start,"prev",current) + start.next = next + current.next = start + start.prev = current start = startnext - startattr = getattr(start,a_syllabe) + startattr = start[a_syllabe] break end - current = getnext(current) + current = current.next end if not startnext then - current = getnext(start) - while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getattr(current,a_syllabe) == startattr do --step 4 - if getattr(current,a_state) == s_pstf then --post-base - startnext = getnext(start) + current = start.next + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do --step 4 + if current[a_state] == s_pstf then --post-base + startnext = start.next head = remove_node(head,start) - local prev = getprev(current) - setfield(start,"prev",prev) - setfield(prev,"next",start) - setfield(start,"next",current) - setfield(current,"prev",start) + local prev = current.prev + start.prev = prev + prev.next = start + start.next = current + current.prev = start start = startnext - startattr = getattr(start,a_syllabe) + startattr = start[a_syllabe] break end - current = getnext(current) + current = current.next end end -- ToDo: determine position for reph with reordering position other than 'before postscript' -- (required for scripts other than dev2) -- leaks if not startnext then - current = getnext(start) + current = start.next local c = nil - while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getattr(current,a_syllabe) == startattr do --step 5 + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do --step 5 if not c then - local char = getchar(current) + local char = current.char -- todo: combine in one if mark_above_below_post[char] and reorder_class[char] ~= "after subscript" then c = current end end - current = getnext(current) + current = current.next end -- here we can loose the old start node: maybe best split cases if c then - startnext = getnext(start) + startnext = start.next head = remove_node(head,start) - local prev = getprev(c) - setfield(start,"prev",prev) - setfield(prev,"next",start) - setfield(start,"next",c) - setfield(c,"prev",start) + local prev = c.prev + start.prev = prev + prev.next = start + start.next = c + c.prev = start -- end start = startnext - startattr = getattr(start,a_syllabe) + startattr = start[a_syllabe] end end -- leaks if not startnext then current = start - local next = getnext(current) - while next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == startfont and getattr(next,a_syllabe) == startattr do --step 6 + local next = current.next + while next and next.id == glyph_code and next.subtype<256 and next.font == startfont and next[a_syllabe] == startattr do --step 6 current = next - next = getnext(current) + next = current.next end if start ~= current then - startnext = getnext(start) + startnext = start.next head = remove_node(head,start) - local next = getnext(current) + local next = current.next if next then - setfield(next,"prev",start) + next.prev = start end - setfield(start,"next",next) - setfield(current,"next",start) - setfield(start,"prev",current) + start.next = next + current.next = start + start.prev = current start = startnext end end @@ -1164,71 +1086,71 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start,k local current = start local startnext = nil local startprev = nil - local startfont = getfont(start) - local startattr = getattr(start,a_syllabe) + local startfont = start.font + local startattr = start[a_syllabe] -- can be fast for loop + caching state - while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getattr(current,a_syllabe) == startattr do - local next = getnext(current) - if halant[getchar(current)] and not getattr(current,a_state) then - if next and getid(next) == glyph_code and getsubtype(next) < 256 and getfont(next) == font and getattr(next,a_syllabe) == startattr then - local char = getchar(next) + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do + local next = current.next + if halant[current.char] and not current[a_state] then + if next and next.id == glyph_code and next.subtype<256 and next.font == font and next[a_syllabe] == startattr then + local char = next.char if char == c_zwnj or char == c_zwj then current = next end end - startnext = getnext(start) + startnext = start.next removenode(start,start) - local next = getnext(current) + local next = current.next if next then - setfield(next,"prev",start) + next.prev = start end - setfield(start,"next",next) - setfield(current,"next",start) - setfield(start,"prev",current) + start.next = next + current.next = start + start.prev = current start = startnext break end current = next end if not startnext then - current = getnext(start) - startattr = getattr(start,a_syllabe) - while current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == startfont and getattr(current,a_syllabe) == startattr do - if not consonant[getchar(current)] and getattr(current,a_state) then --main - startnext = getnext(start) + current = start.next + startattr = start[a_syllabe] + while current and current.id == glyph_code and current.subtype<256 and current.font == startfont and current[a_syllabe] == startattr do + if not consonant[current.char] and current[a_state] then --main + startnext = start.next removenode(start,start) - local prev = getprev(current) - setfield(start,"prev",prev) - setfield(prev,"next",start) - setfield(start,"next",current) - setfield(current,"prev",start) + local prev = current.prev + start.prev = prev + prev.next = start + start.next = current + current.prev = start start = startnext break end - current = getnext(current) + current = current.next end end return head, start, true end function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replacement) - local stop = getnext(start) - local startfont = getfont(start) - while stop and getid(stop) == glyph_code and getsubtype(stop) < 256 and getfont(stop) == startfont do - local char = getchar(stop) + local stop = start.next + local startfont = start.font + while stop and stop.id == glyph_code and stop.subtype<256 and stop.font == startfont do + local char = stop.char if char == c_zwnj or char == c_zwj then - stop = getnext(stop) + stop = stop.next else break end end if stop then - setfield(getfield(stop,"prev"),"next",nil) - setfield(stop,"prev",getprev(start)) + stop.prev.next = nil + stop.prev = start.prev end - local prev = getprev(start) + local prev = start.prev if prev then - setfield(prev,"next",stop) + prev.next = stop end if head == start then head = stop @@ -1238,15 +1160,11 @@ function handlers.devanagari_remove_joiners(head,start,kind,lookupname,replaceme end local valid = { - akhn = true, -- malayalam rphf = true, pref = true, half = true, blwf = true, pstf = true, - pres = true, -- malayalam - blws = true, -- malayalam - psts = true, -- malayalam } local function dev2_initialize(font,attr) @@ -1288,25 +1206,16 @@ local function dev2_initialize(font,attr) local reph = false local chain = dataset[3] if chain ~= 0 then --rphf is result of of chain - -- rphf might be result of other handler/chainproc + --ToDo: rphf might be result of other handler/chainproc else - -- rphf acts on consonant + halant - for k, v in next, ra do - local r = lookupcache[k] - if r then - local h = false - for k, v in next, halant do - local h = r[k] - if h then - reph = h.ligature or false - break - end - end - if reph then - break - end + reph = lookupcache[0x0930] + if reph then + reph = reph[0x094D] + if reph then + reph = reph["ligature"] end end + --ToDo: rphf actualy acts on consonant + halant. This consonant might not necesseraly be 0x0930 ... (but fot dev2 it is) end seqsubset[#seqsubset+1] = { kind, lookupcache, reph } end @@ -1347,37 +1256,32 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa local kind = subset[1] local lookupcache = subset[2] if kind == "rphf" then - for k, v in next, ra do - local r = lookupcache[k] - if r then - for k, v in next, halant do - local h = r[k] - if h then - reph = h.ligature or false - break - end - end - if reph then - break - end + -- todo: rphf might be result of other handler/chainproc + -- todo: rphf actualy acts on consonant + halant. + -- todo: the consonant might not necesseraly be 0x0930 ... (but for devanagari it is) + local lookup = lookupcache[0x0930] + if lookup then + local hit = lookup[0x094D] + if hit then + reph = hit["ligature"] end end local current = start - local last = getnext(stop) + local last = stop.next while current ~= last do if current ~= stop then - local c = locl[current] or getchar(current) + local c = locl[current] or current.char local found = lookupcache[c] if found then - local next = getnext(current) - local n = locl[next] or getchar(next) + local next = current.next + local n = locl[next] or next.char if found[n] then --above-base: rphf Consonant + Halant - local afternext = next ~= stop and getnext(next) - if afternext and zw_char[getchar(afternext)] then -- ZWJ and ZWNJ prevent creation of reph + local afternext = next ~= stop and next.next + if afternext and zw_char[afternext.char] then -- ZWJ and ZWNJ prevent creation of reph current = next - current = getnext(current) + current = current.next elseif current == start then - setattr(current,a_state,s_rphf) + current[a_state] = s_rphf current = next else current = next @@ -1385,111 +1289,98 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa end end end - current = getnext(current) + current = current.next end elseif kind == "pref" then -- why not global? pretty ineffient this way -- this will move to the initializer and we will store the hash in dataset -- todo: reph might also be result of chain - for k, v in next, halant do - local h = lookupcache[k] - if h then - local found = false - for k, v in next, h do - found = v and v.ligature - if found then - pre_base_reordering_consonants[k] = found - break - end - end - if found then - break - end - end + for k, v in lookupcache[0x094D], next do + pre_base_reordering_consonants[k] = v and v["ligature"] --ToDo: reph might also be result of chain end -- local current = start - local last = getnext(stop) + local last = stop.next while current ~= last do if current ~= stop then - local c = locl[current] or getchar(current) + local c = locl[current] or current.char local found = lookupcache[c] if found then - local next = getnext(current) - local n = locl[next] or getchar(next) + local next = current.next + local n = locl[next] or next.char if found[n] then - setattr(current,a_state,s_pref) - setattr(next,a_state,s_pref) + current[a_state] = s_pref + next[a_state] = s_pref current = next end end end - current = getnext(current) + current = current.next end elseif kind == "half" then -- half forms: half / Consonant + Halant local current = start - local last = getnext(stop) + local last = stop.next while current ~= last do if current ~= stop then - local c = locl[current] or getchar(current) + local c = locl[current] or current.char local found = lookupcache[c] if found then - local next = getnext(current) - local n = locl[next] or getchar(next) + local next = current.next + local n = locl[next] or next.char if found[n] then - if next ~= stop and getchar(getnext(next)) == c_zwnj then -- zwnj prevent creation of half + if next ~= stop and next.next.char == c_zwnj then -- zwnj prevent creation of half current = next else - setattr(current,a_state,s_half) + current[a_state] = s_half if not halfpos then halfpos = current end end - current = getnext(current) + current = current.next end end end - current = getnext(current) + current = current.next end elseif kind == "blwf" then -- below-base: blwf / Halant + Consonant local current = start - local last = getnext(stop) + local last = stop.next while current ~= last do if current ~= stop then - local c = locl[current] or getchar(current) + local c = locl[current] or current.char local found = lookupcache[c] if found then - local next = getnext(current) - local n = locl[next] or getchar(next) + local next = current.next + local n = locl[next] or next.char if found[n] then - setattr(current,a_state,s_blwf) - setattr(next,a_state,s_blwf) + current[a_state] = s_blwf + next[a_state] = s_blwf current = next subpos = current end end end - current = getnext(current) + current = current.next end elseif kind == "pstf" then -- post-base: pstf / Halant + Consonant local current = start - local last = getnext(stop) + local last = stop.next while current ~= last do if current ~= stop then - local c = locl[current] or getchar(current) + local c = locl[current] or current.char local found = lookupcache[c] if found then - local next = getnext(current) - local n = locl[next] or getchar(next) + local next = current.next + local n = locl[next] or next.char if found[n] then - setattr(current,a_state,s_pstf) - setattr(next,a_state,s_pstf) + current[a_state] = s_pstf + next[a_state] = s_pstf current = next postpos = current end end end - current = getnext(current) + current = current.next end end end @@ -1501,14 +1392,14 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa local current, base, firstcons = start, nil, nil - if getattr(start,a_state) == s_rphf then + if start[a_state] == s_rphf then -- if syllable starts with Ra + H and script has 'Reph' then exclude Reph from candidates for base consonants - current = getnext(getnext(start)) + current = start.next.next end local function stand_alone(is_nbsp) if current == stop then - stop = getprev(stop) + stop = stop.prev head = remove_node(head,current) free_node(current) return head, stop, nbspaces @@ -1516,36 +1407,36 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa if is_nbsp then nbspaces = nbspaces + 1 end - base = current - current = getnext(current) + base = current + current = current.next if current ~= stop then - local char = getchar(current) + local char = current.char if nukta[char] then - current = getnext(current) - char = getchar(current) + current = current.next + char = current.char end if char == c_zwj then - local next = getnext(current) - if current ~= stop and next ~= stop and halant[getchar(next)] then + local next = current.next + if current ~= stop and next ~= stop and halant[next.char] then current = next - next = getnext(current) - local tmp = getnext(next) + next = current.next + local tmp = next.next local changestop = next == stop - setfield(next,"next",nil) - setattr(current,a_state,s_pref) + next.next = nil + current[a_state] = s_pref current = processcharacters(current,font) - setattr(current,a_state,s_blwf) + current[a_state] = s_blwf current = processcharacters(current,font) - setattr(current,a_state,s_pstf) + current[a_state] = s_pstf current = processcharacters(current,font) - setattr(current,a_state,unsetvalue) - if halant[getchar(current)] then - setfield(getnext(current),"next",tmp) + current[a_state] = unsetvalue + if halant[current.char] then + current.next.next = tmp local nc = copy_node(current) - setfield(current,"char",dotted_circle) + current.char = dotted_circle head = insert_node_after(head,current,nc) else - setfield(current,"next",tmp) -- assumes that result of pref, blwf, or pstf consists of one node + current.next = tmp -- assumes that result of pref, blwf, or pstf consists of one node if changestop then stop = current end @@ -1556,23 +1447,23 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa end end - if current ~= getnext(stop) then + if current ~= stop.next then -- Stand Alone cluster stand_alone() - elseif getchar(current) == c_nbsp then + elseif current.char == c_nbsp then -- Stand Alone cluster stand_alone(true) else -- not Stand Alone cluster - local last = getnext(stop) + local last = stop.next while current ~= last do -- find base consonant - local next = getnext(current) - if consonant[getchar(current)] then - if not (current ~= stop and next ~= stop and halant[getchar(next)] and getchar(getnext(next)) == c_zwj) then + local next = current.next + if consonant[current.char] then + if not (current ~= stop and next ~= stop and halant[next.char] and next.next.char == c_zwj) then if not firstcons then firstcons = current end -- check whether consonant has below-base or post-base form or is pre-base reordering Ra - local a = getattr(current,a_state) + local a = current[a_state] if not (a == s_pref or a == s_blwf or a == s_pstf) then base = current end @@ -1586,13 +1477,13 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa end if not base then - if getattr(start,a_state) == s_rphf then - setattr(start,a_state,unsetvalue) + if start[a_state] == s_rphf then + start[a_state] = unsetvalue end return head, stop, nbspaces else - if getattr(base,a_state) then - setattr(base,a_state,unsetvalue) + if base[a_state] then + base[a_state] = unsetvalue end basepos = base end @@ -1610,32 +1501,22 @@ local function dev2_reorder(head,start,stop,font,attr,nbspaces) -- maybe do a pa local moved = { } local current = start - local last = getnext(stop) + local last = stop.next while current ~= last do - local char, target, cn = locl[current] or getchar(current), nil, getnext(current) --- not so efficient (needed for malayalam) -local tpm = twopart_mark[char] -if tpm then - local extra = copy_node(current) - char = tpm[1] - setfield(current,"char",char) - setfield(extra,"char",tpm[2]) - head = insert_node_after(head,current,extra) -end --- + local char, target, cn = locl[current] or current.char, nil, current.next if not moved[current] and dependent_vowel[char] then if pre_mark[char] then -- Before first half form in the syllable moved[current] = true - local prev = getprev(current) - local next = getnext(current) + local prev = current.prev + local next = current.next if prev then - setfield(prev,"next",next) + prev.next = next end if next then - setfield(next,"prev",prev) + next.prev = prev end if current == stop then - stop = getprev(current) + stop = current.prev end if halfpos == start then if head == start then @@ -1643,13 +1524,13 @@ end end start = current end - local prev = getprev(halfpos) + local prev = halfpos.prev if prev then - setfield(prev,"next",current) + prev.next = current end - setfield(current,"prev",prev) - setfield(halfpos,"prev",current) - setfield(current,"next",halfpos) + current.prev = prev + halfpos.prev = current + current.next = halfpos halfpos = current elseif above_mark[char] then -- After main consonant target = basepos @@ -1671,25 +1552,25 @@ end postpos = current end if mark_above_below_post[char] then - local prev = getprev(current) + local prev = current.prev if prev ~= target then - local next = getnext(current) + local next = current.next if prev then -- not needed, already tested with target - setfield(prev,"next",next) + prev.next = next end if next then - setfield(next,"prev",prev) + next.prev = prev end if current == stop then stop = prev end - local next = getnext(target) + local next = target.next if next then - setfield(next,"prev",current) + next.prev = current end - setfield(current,"next",next) - setfield(target,"next",current) - setfield(current,"prev",target) + current.next = next + target.next = current + current.prev = target end end end @@ -1700,7 +1581,7 @@ end local current, c = start, nil while current ~= stop do - local char = getchar(current) + local char = current.char if halant[char] or stress_tone_mark[char] then if not c then c = current @@ -1708,33 +1589,33 @@ end else c = nil end - local next = getnext(current) - if c and nukta[getchar(next)] then + local next = current.next + if c and nukta[next.char] then if head == c then head = next end if stop == next then stop = current end - local prev = getprev(c) + local prev = c.prev if prev then - setfield(prev,"next",next) + prev.next = next end - setfield(next,"prev",prev) - local nextnext = getnext(next) - setfield(current,"next",nextnext) - local nextnextnext = getnext(nextnext) + next.prev = prev + local nextnext = next.next + current.next = nextnext + local nextnextnext = nextnext.next if nextnextnext then - setfield(nextnextnext,"prev",current) + nextnextnext.prev = current end - setfield(c,"prev",nextnext) - setfield(nextnext,"next",c) + c.prev = nextnext + nextnext.next = c end if stop == current then break end - current = getnext(current) + current = current.next end - if getchar(base) == c_nbsp then + if base.char == c_nbsp then nbspaces = nbspaces - 1 head = remove_node(head, base) free_node(base) @@ -1758,30 +1639,30 @@ for k, v in next, halant do separator[k] = true end local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowel -- why two variants ... the comment suggests that it's the same ruleset - local n = getnext(c) + local n = c.next if not n then return c end if variant == 1 then - local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font - if v and nukta[getchar(n)] then - n = getnext(n) + local v = n.id == glyph_code and n.subtype<256 and n.font == font + if v and nukta[n.char] then + n = n.next if n then - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font end end if n and v then - local nn = getnext(n) - if nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font then - local nnn = getnext(nn) - if nnn and getid(nnn) == glyph_code and getsubtype(nnn) < 256 and getfont(nnn) == font then - local nnc = getchar(nn) - local nnnc = getchar(nnn) + local nn = n.next + if nn and nn.id == glyph_code and nn.subtype<256 and nn.font == font then + local nnn = nn.next + if nnn and nnn.id == glyph_code and nnn.subtype<256 and nnn.font == font then + local nnc = nn.char + local nnnc = nnn.char if nnc == c_zwj and consonant[nnnc] then c = nnn elseif (nnc == c_zwnj or nnc == c_zwj) and halant[nnnc] then - local nnnn = getnext(nnn) - if nnnn and getid(nnnn) == glyph_code and consonant[getchar(nnnn)] and getsubtype(nnnn) < 256 and getfont(nnnn) == font then + local nnnn = nnn.next + if nnnn and nnnn.id == glyph_code and consonant[nnnn.char] and nnnn.subtype<256 and nnnn.font == font then c = nnnn end end @@ -1789,94 +1670,94 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end end elseif variant == 2 then - if getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then + if n.id == glyph_code and nukta[n.char] and n.subtype<256 and n.font == font then c = n end - n = getnext(c) - if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then - local nn = getnext(n) + n = c.next + if n and n.id == glyph_code and n.subtype<256 and n.font == font then + local nn = n.next if nn then - local nv = getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font - if nv and zw_char[getchar(n)] then + local nv = nn.id == glyph_code and nn.subtype<256 and nn.font == font + if nv and zw_char[n.char] then n = nn - nn = getnext(nn) - nv = nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font + nn = nn.next + nv = nn and nn.id == glyph_code and nn.subtype<256 and nn.font == font end - if nv and halant[getchar(n)] and consonant[getchar(nn)] then + if nv and halant[n.char] and consonant[nn.char] then c = nn end end end end -- c = ms_matra(c) - local n = getnext(c) + local n = c.next if not n then return c end - local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + local v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - local char = getchar(n) + local char = n.char if dependent_vowel[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if nukta[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if halant[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if vowel_modifier[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if stress_tone_mark[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if stress_tone_mark[char] then return n @@ -1886,38 +1767,38 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe end local function analyze_next_chars_two(c,font) - local n = getnext(c) + local n = c.next if not n then return c end - if getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then + if n.id == glyph_code and nukta[n.char] and n.subtype<256 and n.font == font then c = n end n = c while true do - local nn = getnext(n) - if nn and getid(nn) == glyph_code and getsubtype(nn) < 256 and getfont(nn) == font then - local char = getchar(nn) + local nn = n.next + if nn and nn.id == glyph_code and nn.subtype<256 and nn.font == font then + local char = nn.char if halant[char] then n = nn - local nnn = getnext(nn) - if nnn and getid(nnn) == glyph_code and zw_char[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then + local nnn = nn.next + if nnn and nnn.id == glyph_code and zw_char[nnn.char] and nnn.subtype<256 and nnn.font == font then n = nnn end elseif char == c_zwnj or char == c_zwj then -- n = nn -- not here (?) - local nnn = getnext(nn) - if nnn and getid(nnn) == glyph_code and halant[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then + local nnn = nn.next + if nnn and nnn.id == glyph_code and halant[nnn.char] and nnn.subtype<256 and nnn.font == font then n = nnn end else break end - local nn = getnext(n) - if nn and getid(nn) == glyph_code and consonant[getchar(nn)] and getsubtype(nn) < 256 and getfont(nn) == font then + local nn = n.next + if nn and nn.id == glyph_code and consonant[nn.char] and nn.subtype<256 and nn.font == font then n = nn - local nnn = getnext(nn) - if nnn and getid(nnn) == glyph_code and nukta[getchar(nnn)] and getsubtype(nnn) < 256 and getfont(nnn) == font then + local nnn = nn.next + if nnn and nnn.id == glyph_code and nukta[nnn.char] and nnn.subtype<256 and nnn.font == font then n = nnn end c = n @@ -1933,114 +1814,114 @@ local function analyze_next_chars_two(c,font) -- This shouldn't happen I guess. return end - local n = getnext(c) + local n = c.next if not n then return c end - local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + local v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - local char = getchar(n) + local char = n.char if char == c_anudatta then c = n - n = getnext(c) + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if halant[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char if char == c_zwnj or char == c_zwj then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end else -- c = ms_matra(c) -- same as one if dependent_vowel[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if nukta[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if halant[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end end -- same as one if vowel_modifier[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if stress_tone_mark[char] then - c = getnext(c) - n = getnext(c) + c = c.next + n = c.next if not n then return c end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then return c end - char = getchar(n) + char = n.char end if stress_tone_mark[char] then return n @@ -2052,9 +1933,9 @@ end local function inject_syntax_error(head,current,mark) local signal = copy_node(current) if mark == pre_mark then - setfield(signal,"char",dotted_circle) + signal.char = dotted_circle else - setfield(current,"char",dotted_circle) + current.char = dotted_circle end return insert_node_after(head,current,signal) end @@ -2063,32 +1944,31 @@ end -- a lot. Common code has been synced. function methods.deva(head,font,attr) - head = tonut(head) local current = head local start = true local done = false local nbspaces = 0 while current do - if getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font then + if current.id == glyph_code and current.subtype<256 and current.font == font then done = true local syllablestart = current local syllableend = nil local c = current - local n = getnext(c) - if n and ra[getchar(c)] and getid(n) == glyph_code and halant[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then - local n = getnext(n) - if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then + local n = c.next + if n and c.char == c_ra and n.id == glyph_code and halant[n.char] and n.subtype<256 and n.font == font then + local n = n.next + if n and n.id == glyph_code and n.subtype<256 and n.font == font then c = n end end - local standalone = getchar(c) == c_nbsp + local standalone = c.char == c_nbsp if standalone then - local prev = getprev(current) + local prev = current.prev if not prev then -- begin of paragraph or box - elseif getid(prev) ~= glyph_code or getsubtype(prev) >= 256 or getfont(prev) ~= font then + elseif prev.id ~= glyph_code or prev.subtype>=256 or prev.font ~= font then -- different font or language so quite certainly a different word - elseif not separator[getchar(prev)] then + elseif not separator[prev.char] then -- something that separates words else standalone = false @@ -2097,61 +1977,61 @@ function methods.deva(head,font,attr) if standalone then -- stand alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] local syllableend = analyze_next_chars_one(c,font,2) - current = getnext(syllableend) + current = syllableend.next if syllablestart ~= syllableend then head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current = getnext(current) + current = current.next end else - -- we can delay the getsubtype(n) and getfont(n) and test for say halant first + -- we can delay the n.subtype and n.font and test for say halant first -- as an table access is faster than two function calls (subtype and font are -- pseudo fields) but the code becomes messy (unless we make it a function) - local char = getchar(current) + local char = current.char if consonant[char] then -- syllable containing consonant local prevc = true while prevc do prevc = false - local n = getnext(current) + local n = current.next if not n then break end - local v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + local v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then break end - local c = getchar(n) + local c = n.char if nukta[c] then - n = getnext(n) + n = n.next if not n then break end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then break end - c = getchar(n) + c = n.char end if halant[c] then - n = getnext(n) + n = n.next if not n then break end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then break end - c = getchar(n) + c = n.char if c == c_zwnj or c == c_zwj then - n = getnext(n) + n = n.next if not n then break end - v = getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font + v = n.id == glyph_code and n.subtype<256 and n.font == font if not v then break end - c = getchar(n) + c = n.char end if consonant[c] then prevc = true @@ -2159,77 +2039,77 @@ function methods.deva(head,font,attr) end end end - local n = getnext(current) - if n and getid(n) == glyph_code and nukta[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then + local n = current.next + if n and n.id == glyph_code and nukta[n.char] and n.subtype<256 and n.font == font then -- nukta (not specified in Microsft Devanagari OpenType specification) current = n - n = getnext(current) + n = current.next end syllableend = current current = n if current then - local v = getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font + local v = current.id == glyph_code and current.subtype<256 and current.font == font if v then - if halant[getchar(current)] then + if halant[current.char] then -- syllable containing consonant without vowels: {C + [Nukta] + H} + C + H - local n = getnext(current) - if n and getid(n) == glyph_code and zw_char[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then + local n = current.next + if n and n.id == glyph_code and zw_char[n.char] and n.subtype<256 and n.font == font then -- code collapsed, probably needs checking with intention syllableend = n - current = getnext(n) + current = n.next else syllableend = current current = n end else -- syllable containing consonant with vowels: {C + [Nukta] + H} + C + [M] + [VM] + [SM] - local c = getchar(current) + local c = current.char if dependent_vowel[c] then syllableend = current - current = getnext(current) - v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font + current = current.next + v = current and current.id == glyph_code and current.subtype<256 and current.font == font if v then - c = getchar(current) + c = current.char end end if v and vowel_modifier[c] then syllableend = current - current = getnext(current) - v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font + current = current.next + v = current and current.id == glyph_code and current.subtype<256 and current.font == font if v then - c = getchar(current) + c = current.char end end if v and stress_tone_mark[c] then syllableend = current - current = getnext(current) + current = current.next end end end end if syllablestart ~= syllableend then head, current, nbspaces = deva_reorder(head,syllablestart,syllableend,font,attr,nbspaces) - current = getnext(current) + current = current.next end elseif independent_vowel[char] then -- syllable without consonants: VO + [VM] + [SM] syllableend = current - current = getnext(current) + current = current.next if current then - local v = getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font + local v = current.id == glyph_code and current.subtype<256 and current.font == font if v then - local c = getchar(current) + local c = current.char if vowel_modifier[c] then syllableend = current - current = getnext(current) - v = current and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font + current = current.next + v = current and current.id == glyph_code and current.subtype<256 and current.font == font if v then - c = getchar(current) + c = current.char end end if v and stress_tone_mark[c] then syllableend = current - current = getnext(current) + current = current.next end end end @@ -2238,11 +2118,11 @@ function methods.deva(head,font,attr) if mark then head, current = inject_syntax_error(head,current,mark) end - current = getnext(current) + current = current.next end end else - current = getnext(current) + current = current.next end start = false end @@ -2251,7 +2131,7 @@ function methods.deva(head,font,attr) head = replace_all_nbsp(head) end - head = tonode(head) + head = typesetters.characters.handler(head) return head, done end @@ -2262,7 +2142,6 @@ end -- handler(head,start,kind,lookupname,lookupmatch,sequence,lookuphash,1) function methods.dev2(head,font,attr) - head = tonut(head) local current = head local start = true local done = false @@ -2270,18 +2149,18 @@ function methods.dev2(head,font,attr) local nbspaces = 0 while current do local syllablestart, syllableend = nil, nil - if getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font then + if current.id == glyph_code and current.subtype<256 and current.font == font then done = true syllablestart = current local c = current - local n = getnext(current) - if n and ra[getchar(c)] and getid(n) == glyph_code and halant[getchar(n)] and getsubtype(n) < 256 and getfont(n) == font then - local n = getnext(n) - if n and getid(n) == glyph_code and getsubtype(n) < 256 and getfont(n) == font then + local n = current.next + if n and c.char == c_ra and n.id == glyph_code and halant[n.char] and n.subtype<256 and n.font == font then + local n = n.next + if n and n.id == glyph_code and n.subtype<256 and n.font == font then c = n end end - local char = getchar(c) + local char = c.char if independent_vowel[char] then -- vowel-based syllable: [Ra+H]+V+[N]+[<[<ZWJ|ZWNJ>]+H+C|ZWJ+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] current = analyze_next_chars_one(c,font,1) @@ -2290,12 +2169,12 @@ function methods.dev2(head,font,attr) local standalone = char == c_nbsp if standalone then nbspaces = nbspaces + 1 - local p = getprev(current) + local p = current.prev if not p then -- begin of paragraph or box - elseif getid(p) ~= glyph_code or getsubtype(p) >= 256 or getfont(p) ~= font then + elseif p.id ~= glyph_code or p.subtype>=256 or p.font ~= font then -- different font or language so quite certainly a different word - elseif not separator[getchar(p)] then + elseif not separator[p.char] then -- something that separates words else standalone = false @@ -2305,7 +2184,7 @@ function methods.dev2(head,font,attr) -- Stand Alone cluster (at the start of the word only): #[Ra+H]+NBSP+[N]+[<[<ZWJ|ZWNJ>]+H+C>]+[{M}+[N]+[H]]+[SM]+[(VD)] current = analyze_next_chars_one(c,font,2) syllableend = current - elseif consonant[getchar(current)] then + elseif consonant[current.char] then -- WHY current INSTEAD OF c ? -- Consonant syllable: {C+[N]+<H+[<ZWNJ|ZWJ>]|<ZWNJ|ZWJ>+H>} + C+[N]+[A] + [< H+[<ZWNJ|ZWJ>] | {M}+[N]+[H]>]+[SM]+[(VD)] @@ -2317,33 +2196,28 @@ function methods.dev2(head,font,attr) if syllableend then syllabe = syllabe + 1 local c = syllablestart - local n = getnext(syllableend) + local n = syllableend.next while c ~= n do - setattr(c,a_syllabe,syllabe) - c = getnext(c) + c[a_syllabe] = syllabe + c = c.next end end if syllableend and syllablestart ~= syllableend then head, current, nbspaces = dev2_reorder(head,syllablestart,syllableend,font,attr,nbspaces) end - if not syllableend and getid(current) == glyph_code and getsubtype(current) < 256 and getfont(current) == font and not getattr(current,a_state) then - local mark = mark_four[getchar(current)] + if not syllableend and current.id == glyph_code and current.subtype<256 and current.font == font and not current[a_state] then + local mark = mark_four[current.char] if mark then head, current = inject_syntax_error(head,current,mark) end end start = false - current = getnext(current) + current = current.next end if nbspaces > 0 then head = replace_all_nbsp(head) end - head = tonode(head) - return head, done end - -methods.mlym = methods.deva -methods.mlm2 = methods.dev2 diff --git a/tex/context/base/font-otf.lua b/tex/context/base/font-otf.lua index eb28bc368..51c2af00f 100644 --- a/tex/context/base/font-otf.lua +++ b/tex/context/base/font-otf.lua @@ -20,7 +20,7 @@ local type, next, tonumber, tostring = type, next, tonumber, tostring local abs = math.abs local insert = table.insert local lpegmatch = lpeg.match -local reversed, concat, remove, sortedkeys = table.reversed, table.concat, table.remove, table.sortedkeys +local reversed, concat, remove = table.reversed, table.concat, table.remove local ioflush = io.flush local fastcopy, tohash, derivetable = table.fastcopy, table.tohash, table.derive local formatters = string.formatters @@ -48,7 +48,7 @@ local otf = fonts.handlers.otf otf.glists = { "gsub", "gpos" } -otf.version = 2.751 -- beware: also sync font-mis.lua +otf.version = 2.749 -- beware: also sync font-mis.lua otf.cache = containers.define("fonts", "otf", otf.version, true) local fontdata = fonts.hashes.identifiers @@ -106,8 +106,6 @@ function otf.fileformat(filename) return formats.otf, suffix == "otf" elseif leader == "ttcf" then return formats.ttc, suffix == "ttc" - -- elseif leader == "true" then - -- return formats.ttf, suffix == "ttf" elseif suffix == "ttc" then return formats.ttc, true elseif suffix == "dfont" then @@ -239,7 +237,7 @@ local valid_fields = table.tohash { "upos", "use_typo_metrics", "uwidth", - "validation_state", + -- "validation_state", "version", "vert_base", "weight", @@ -770,7 +768,7 @@ actions["prepare glyphs"] = function(data,filename,raw) } local altuni = glyph.altuni if altuni then - -- local d + local d for i=1,#altuni do local a = altuni[i] local u = a.unicode @@ -785,15 +783,15 @@ actions["prepare glyphs"] = function(data,filename,raw) vv = { [u] = unicode } variants[v] = vv end - -- elseif d then - -- d[#d+1] = u - -- else - -- d = { u } + elseif d then + d[#d+1] = u + else + d = { u } end end - -- if d then - -- duplicates[unicode] = d -- is this needed ? - -- end + if d then + duplicates[unicode] = d + end end else report_otf("potential problem: glyph %U is used but empty",index) @@ -821,7 +819,6 @@ actions["check encoding"] = function(data,filename,raw) local mapdata = raw.map or { } local unicodetoindex = mapdata and mapdata.map or { } - local indextounicode = mapdata and mapdata.backmap or { } -- local encname = lower(data.enc_name or raw.enc_name or mapdata.enc_name or "") local encname = lower(data.enc_name or mapdata.enc_name or "") local criterium = 0xFFFF -- for instance cambria has a lot of mess up there @@ -832,81 +829,42 @@ actions["check encoding"] = function(data,filename,raw) if trace_loading then report_otf("checking embedded unicode map %a",encname) end - -- if false then - -- for unicode, index in next, unicodetoindex do -- altuni already covers this - -- if unicode <= criterium and not descriptions[unicode] then - -- local parent = indices[index] -- why nil? - -- if not parent then - -- report_otf("weird, unicode %U points to nowhere with index %H",unicode,index) - -- else - -- local parentdescription = descriptions[parent] - -- if parentdescription then - -- local altuni = parentdescription.altuni - -- if not altuni then - -- altuni = { { unicode = unicode } } - -- parentdescription.altuni = altuni - -- duplicates[parent] = { unicode } - -- else - -- local done = false - -- for i=1,#altuni do - -- if altuni[i].unicode == unicode then - -- done = true - -- break - -- end - -- end - -- if not done then - -- -- let's assume simple cjk reuse - -- insert(altuni,{ unicode = unicode }) - -- insert(duplicates[parent],unicode) - -- end - -- end - -- -- if trace_loading then - -- -- report_otf("weird, unicode %U points to nowhere with index %H",unicode,index) - -- -- end - -- else - -- report_otf("weird, unicode %U points to %U with index %H",unicode,index) - -- end - -- end - -- end - -- end - -- else - local hash = { } - for index, unicode in next, indices do -- indextounicode - hash[index] = descriptions[unicode] - end - local reported = { } - for unicode, index in next, unicodetoindex do - if not descriptions[unicode] then - local d = hash[index] - if d then - if d.unicode ~= unicode then - local c = d.copies - if c then - c[unicode] = true - else - d.copies = { [unicode] = true } + for unicode, index in next, unicodetoindex do -- altuni already covers this + if unicode <= criterium and not descriptions[unicode] then + local parent = indices[index] -- why nil? + if not parent then + report_otf("weird, unicode %U points to nowhere with index %H",unicode,index) + else + local parentdescription = descriptions[parent] + if parentdescription then + local altuni = parentdescription.altuni + if not altuni then + altuni = { { unicode = unicode } } + parentdescription.altuni = altuni + duplicates[parent] = { unicode } + else + local done = false + for i=1,#altuni do + if altuni[i].unicode == unicode then + done = true + break + end end + if not done then + -- let's assume simple cjk reuse + insert(altuni,{ unicode = unicode }) + insert(duplicates[parent],unicode) + end + end + if trace_loading then + report_otf("weird, unicode %U points to nowhere with index %H",unicode,index) end - elseif not reported[i] then - report_otf("missing index %i",index) - reported[i] = true + else + report_otf("weird, unicode %U points to %U with index %H",unicode,index) end end end - for index, data in next, hash do -- indextounicode - data.copies = sortedkeys(data.copies) - end - for index, unicode in next, indices do -- indextounicode - local description = hash[index] - local copies = description.copies - if copies then - duplicates[unicode] = copies - description.copies = nil - else - report_otf("copies but no unicode parent %U",unicode) - end - end - -- end + end elseif properties.cidinfo then report_otf("warning: no unicode map, used cidmap %a",properties.cidinfo.usedname) else @@ -914,15 +872,12 @@ actions["check encoding"] = function(data,filename,raw) end if mapdata then - mapdata.map = { } -- clear some memory - mapdata.backmap = { } -- clear some memory + mapdata.map = { } -- clear some memory end end -- for the moment we assume that a font with lookups will not use --- altuni so we stick to kerns only .. alternatively we can always --- do an indirect lookup uni_to_uni . but then we need that in --- all lookups +-- altuni so we stick to kerns only actions["add duplicates"] = function(data,filename,raw) local descriptions = data.descriptions @@ -933,38 +888,29 @@ actions["add duplicates"] = function(data,filename,raw) local duplicates = resources.duplicates for unicode, d in next, duplicates do - local nofduplicates = #d - if nofduplicates > 4 then - if trace_loading then - report_otf("ignoring excessive duplicates of %U (n=%s)",unicode,nofduplicates) - end - else - for i=1,nofduplicates do - local u = d[i] - if not descriptions[u] then - local description = descriptions[unicode] - local n = 0 - for _, description in next, descriptions do - if kerns then - local kerns = description.kerns - for _, k in next, kerns do - local ku = k[unicode] - if ku then - k[u] = ku - n = n + 1 - end + for i=1,#d do + local u = d[i] + if not descriptions[u] then + local description = descriptions[unicode] + local duplicate = table.copy(description) -- else packing problem + duplicate.comment = format("copy of U+%05X", unicode) + descriptions[u] = duplicate + local n = 0 + for _, description in next, descriptions do + if kerns then + local kerns = description.kerns + for _, k in next, kerns do + local ku = k[unicode] + if ku then + k[u] = ku + n = n + 1 end end - -- todo: lookups etc - end - if u > 0 then - local duplicate = table.copy(description) -- else packing problem - duplicate.comment = format("copy of U+%05X", unicode) - descriptions[u] = duplicate - if trace_loading then - report_otf("duplicating %U to %U with index %H (%s kerns)",unicode,u,description.index,n) - end end + -- todo: lookups etc + end + if trace_loading then + report_otf("duplicating %U to %U with index %H (%s kerns)",unicode,u,description.index,n) end end end @@ -1772,13 +1718,6 @@ actions["check metadata"] = function(data,filename,raw) ttftables[i].data = "deleted" end end - -- - if metadata.validation_state and table.contains(metadata.validation_state,"bad_ps_fontname") then - local name = file.nameonly(filename) - metadata.fontname = "bad-fontname-" .. name - metadata.fullname = "bad-fullname-" .. name - end - -- end actions["cleanup tables"] = function(data,filename,raw) @@ -2145,24 +2084,6 @@ local function otftotfm(specification) local features = specification.features.normal local rawdata = otf.load(filename,sub,features and features.featurefile) if rawdata and next(rawdata) then - local descriptions = rawdata.descriptions - local duplicates = rawdata.resources.duplicates - if duplicates then - local nofduplicates, nofduplicated = 0, 0 - for parent, list in next, duplicates do - for i=1,#list do - local unicode = list[i] - if not descriptions[unicode] then - descriptions[unicode] = descriptions[parent] -- or copy - nofduplicated = nofduplicated + 1 - end - end - nofduplicates = nofduplicates + #list - end - if trace_otf and nofduplicated ~= nofduplicates then - report_otf("%i extra duplicates copied out of %i",nofduplicated,nofduplicates) - end - end rawdata.lookuphash = { } tfmdata = copytotfm(rawdata,cache_id) if tfmdata and next(tfmdata) then diff --git a/tex/context/base/font-otn.lua b/tex/context/base/font-otn.lua index 75e95749c..c57be5f02 100644 --- a/tex/context/base/font-otn.lua +++ b/tex/context/base/font-otn.lua @@ -6,14 +6,8 @@ if not modules then modules = { } end modules ['font-otn'] = { license = "see context related readme files", } --- this is a context version which can contain experimental code, but when we --- have serious patches we also need to change the other two font-otn files - -- preprocessors = { "nodes" } --- anchor class : mark, mkmk, curs, mklg (todo) --- anchor type : mark, basechar, baselig, basemark, centry, cexit, max (todo) - -- this is still somewhat preliminary and it will get better in due time; -- much functionality could only be implemented thanks to the husayni font -- of Idris Samawi Hamid to who we dedicate this module. @@ -177,28 +171,12 @@ registertracker("otf.injections","nodes.injections") registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing") -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local insert_node_after = nuts.insert_after -local delete_node = nuts.delete -local copy_node = nuts.copy -local find_node_tail = nuts.tail -local flush_node_list = nuts.flush_list -local end_of_math = nuts.end_of_math +local insert_node_after = node.insert_after +local delete_node = nodes.delete +local copy_node = node.copy +local find_node_tail = node.tail or node.slide +local flush_node_list = node.flush_list +local end_of_math = node.end_of_math local setmetatableindex = table.setmetatableindex @@ -354,11 +332,11 @@ end -- and indices. local function copy_glyph(g) -- next and prev are untouched ! - local components = getfield(g,"components") + local components = g.components if components then - setfield(g,"components",nil) + g.components = nil local n = copy_node(g) - setfield(g,"components",components) + g.components = components return n else return copy_node(g) @@ -368,28 +346,28 @@ end -- start is a mark and we need to keep that one local function markstoligature(kind,lookupname,head,start,stop,char) - if start == stop and getchar(start) == char then + if start == stop and start.char == char then return head, start else - local prev = getprev(start) - local next = getnext(stop) - setfield(start,"prev",nil) - setfield(stop,"next",nil) + local prev = start.prev + local next = stop.next + start.prev = nil + stop.next = nil local base = copy_glyph(start) if head == start then head = base end - setfield(base,"char",char) - setfield(base,"subtype",ligature_code) - setfield(base,"components",start) + base.char = char + base.subtype = ligature_code + base.components = start if prev then - setfield(prev,"next",base) + prev.next = base end if next then - setfield(next,"prev",base) + next.prev = base end - setfield(base,"next",next) - setfield(base,"prev",prev) + base.next = next + base.prev = prev return head, base end end @@ -402,17 +380,17 @@ end -- third component. local function getcomponentindex(start) - if getid(start) ~= glyph_code then + if start.id ~= glyph_code then return 0 - elseif getsubtype(start) == ligature_code then + elseif start.subtype == ligature_code then local i = 0 - local components = getfield(start,"components") + local components = start.components while components do i = i + getcomponentindex(components) - components = getnext(components) + components = components.next end return i - elseif not marks[getchar(start)] then + elseif not marks[start.char] then return 1 else return 0 @@ -422,29 +400,29 @@ end -- eventually we will do positioning in an other way (needs addional w/h/d fields) local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head - if start == stop and getchar(start) == char then - setfield(start,"char",char) + if start == stop and start.char == char then + start.char = char return head, start end - local prev = getprev(start) - local next = getnext(stop) - setfield(start,"prev",nil) - setfield(stop,"next",nil) + local prev = start.prev + local next = stop.next + start.prev = nil + stop.next = nil local base = copy_glyph(start) if start == head then head = base end - setfield(base,"char",char) - setfield(base,"subtype",ligature_code) - setfield(base,"components",start) -- start can have components + base.char = char + base.subtype = ligature_code + base.components = start -- start can have components if prev then - setfield(prev,"next",base) + prev.next = base end if next then - setfield(next,"prev",base) + next.prev = base end - setfield(base,"next",next) - setfield(base,"prev",prev) + base.next = next + base.prev = prev if not discfound then local deletemarks = markflag ~= "mark" local components = start @@ -454,35 +432,35 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun local current = base -- first we loop over the glyphs in start .. stop while start do - local char = getchar(start) + local char = start.char if not marks[char] then baseindex = baseindex + componentindex componentindex = getcomponentindex(start) elseif not deletemarks then -- quite fishy - setattr(start,a_ligacomp,baseindex + (getattr(start,a_ligacomp) or componentindex)) + start[a_ligacomp] = baseindex + (start[a_ligacomp] or componentindex) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp)) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) end head, current = insert_node_after(head,current,copy_node(start)) -- unlikely that mark has components elseif trace_marks then logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char)) end - start = getnext(start) + start = start.next end -- we can have one accent as part of a lookup and another following -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added) - local start = getnext(current) - while start and getid(start) == glyph_code do - local char = getchar(start) + local start = current.next + while start and start.id == glyph_code do + local char = start.char if marks[char] then - setattr(start,a_ligacomp,baseindex + (getattr(start,a_ligacomp) or componentindex)) + start[a_ligacomp] = baseindex + (start[a_ligacomp] or componentindex) if trace_marks then - logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp)) + logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) end else break end - start = getnext(start) + start = start.next end end return head, base @@ -490,9 +468,9 @@ end function handlers.gsub_single(head,start,kind,lookupname,replacement) if trace_singles then - logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement)) + logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement)) end - setfield(start,"char",replacement) + start.char = replacement return head, start, true end @@ -519,7 +497,7 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives return false, trace_alternatives and formatters["invalid value %a, %s"](value,"out of range") end elseif value == 0 then - return getchar(start), trace_alternatives and formatters["invalid value %a, %s"](value,"no change") + return start.char, trace_alternatives and formatters["invalid value %a, %s"](value,"no change") elseif value < 1 then return alternatives[1], trace_alternatives and formatters["invalid value %a, taking %a"](value,1) else @@ -531,30 +509,30 @@ end local function multiple_glyphs(head,start,multiple,ignoremarks) local nofmultiples = #multiple if nofmultiples > 0 then - setfield(start,"char",multiple[1]) + start.char = multiple[1] if nofmultiples > 1 then - local sn = getnext(start) + local sn = start.next for k=2,nofmultiples do -- todo: use insert_node -- untested: -- --- while ignoremarks and marks[getchar(sn)] then --- local sn = getnext(sn) +-- while ignoremarks and marks[sn.char] then +-- local sn = sn.next -- end local n = copy_node(start) -- ignore components - setfield(n,"char",multiple[k]) - setfield(n,"next",sn) - setfield(n,"prev",start) + n.char = multiple[k] + n.next = sn + n.prev = start if sn then - setfield(sn,"prev",n) + sn.prev = n end - setfield(start,"next",n) + start.next = n start = n end end return head, start, true else if trace_multiples then - logprocess("no multiple for %s",gref(getchar(start))) + logprocess("no multiple for %s",gref(start.char)) end return head, start, false end @@ -565,12 +543,12 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence local choice, comment = get_alternative_glyph(start,alternative,value,trace_alternatives) if choice then if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment) + logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(start.char),choice,gref(choice),comment) end - setfield(start,"char",choice) + start.char = choice else if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment) + logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(start.char),comment) end end return head, start, true @@ -578,23 +556,23 @@ end function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence) if trace_multiples then - logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple)) + logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple)) end return multiple_glyphs(head,start,multiple,sequence.flags[1]) end function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) - local s, stop, discfound = getnext(start), nil, false - local startchar = getchar(start) + local s, stop, discfound = start.next, nil, false + local startchar = start.char if marks[startchar] then while s do - local id = getid(s) - if id == glyph_code and getfont(s) == currentfont and getsubtype(s)<256 then - local lg = ligature[getchar(s)] + local id = s.id + if id == glyph_code and s.font == currentfont and s.subtype<256 then + local lg = ligature[s.char] if lg then stop = s ligature = lg - s = getnext(s) + s = s.next else break end @@ -606,9 +584,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) local lig = ligature.ligature if lig then if trace_ligatures then - local stopchar = getchar(stop) + local stopchar = stop.char head, start = markstoligature(kind,lookupname,head,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start))) + logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) else head, start = markstoligature(kind,lookupname,head,start,stop,lig) end @@ -620,18 +598,18 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) else local skipmark = sequence.flags[1] while s do - local id = getid(s) - if id == glyph_code and getsubtype(s)<256 then - if getfont(s) == currentfont then - local char = getchar(s) + local id = s.id + if id == glyph_code and s.subtype<256 then + if s.font == currentfont then + local char = s.char if skipmark and marks[char] then - s = getnext(s) + s = s.next else local lg = ligature[char] if lg then stop = s ligature = lg - s = getnext(s) + s = s.next else break end @@ -641,7 +619,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) end elseif id == disc_code then discfound = true - s = getnext(s) + s = s.next else break end @@ -650,20 +628,21 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) if lig then if stop then if trace_ligatures then - local stopchar = getchar(stop) + local stopchar = stop.char head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start))) + logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) else head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound) end + return head, start, true else -- weird but happens (in some arabic font) - setfield(start,"char",lig) + start.char = lig if trace_ligatures then logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig)) end + return head, start, true end - return head, start, true else -- weird but happens end @@ -677,16 +656,16 @@ we need to explicitly test for basechar, baselig and basemark entries.</p> --ldx]]-- function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence) - local markchar = getchar(start) + local markchar = start.char if marks[markchar] then - local base = getprev(start) -- [glyph] [start=mark] - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then - local basechar = getchar(base) + local base = start.prev -- [glyph] [start=mark] + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then + local basechar = base.char if marks[basechar] then while true do - base = getprev(base) - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then - basechar = getchar(base) + base = base.prev + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then + basechar = base.char if not marks[basechar] then break end @@ -738,16 +717,16 @@ end function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence) -- check chainpos variant - local markchar = getchar(start) + local markchar = start.char if marks[markchar] then - local base = getprev(start) -- [glyph] [optional marks] [start=mark] - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then - local basechar = getchar(base) + local base = start.prev -- [glyph] [optional marks] [start=mark] + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then + local basechar = base.char if marks[basechar] then while true do - base = getprev(base) - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then - basechar = getchar(base) + base = base.prev + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then + basechar = base.char if not marks[basechar] then break end @@ -759,7 +738,7 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ end end end - local index = getattr(start,a_ligacomp) + local index = start[a_ligacomp] local baseanchors = descriptions[basechar] if baseanchors then baseanchors = baseanchors.anchors @@ -806,22 +785,22 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ end function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence) - local markchar = getchar(start) + local markchar = start.char if marks[markchar] then - local base = getprev(start) -- [glyph] [basemark] [start=mark] - local slc = getattr(start,a_ligacomp) + local base = start.prev -- [glyph] [basemark] [start=mark] + local slc = start[a_ligacomp] if slc then -- a rather messy loop ... needs checking with husayni while base do - local blc = getattr(base,a_ligacomp) + local blc = base[a_ligacomp] if blc and blc ~= slc then - base = getprev(base) + base = base.prev else break end end end - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then -- subtype test can go - local basechar = getchar(base) + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then -- subtype test can go + local basechar = base.char local baseanchors = descriptions[basechar] if baseanchors then baseanchors = baseanchors.anchors @@ -861,21 +840,21 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence end function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) -- to be checked - local alreadydone = cursonce and getattr(start,a_cursbase) + local alreadydone = cursonce and start[a_cursbase] if not alreadydone then local done = false - local startchar = getchar(start) + local startchar = start.char if marks[startchar] then if trace_cursive then logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar)) end else - local nxt = getnext(start) - while not done and nxt and getid(nxt) == glyph_code and getfont(nxt) == currentfont and getsubtype(nxt)<256 do - local nextchar = getchar(nxt) + local nxt = start.next + while not done and nxt and nxt.id == glyph_code and nxt.font == currentfont and nxt.subtype<256 do + local nextchar = nxt.char if marks[nextchar] then -- should not happen (maybe warning) - nxt = getnext(nxt) + nxt = nxt.next else local entryanchors = descriptions[nextchar] if entryanchors then @@ -910,14 +889,14 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) return head, start, done else if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone) + logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) end return head, start, false end end function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence) - local startchar = getchar(start) + local startchar = start.char local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar]) if trace_kerns then logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h) @@ -928,19 +907,19 @@ end function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too -- todo: kerns in components of ligatures - local snext = getnext(start) + local snext = start.next if not snext then return head, start, false else local prev, done = start, false local factor = tfmdata.parameters.factor local lookuptype = lookuptypes[lookupname] - while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do - local nextchar = getchar(snext) + while snext and snext.id == glyph_code and snext.font == currentfont and snext.subtype<256 do + local nextchar = snext.char local krn = kerns[nextchar] if not krn and marks[nextchar] then prev = snext - snext = getnext(snext) + snext = snext.next else if not krn then -- skip @@ -948,14 +927,14 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) if lookuptype == "pair" then -- probably not needed local a, b = krn[2], krn[3] if a and #a > 0 then - local startchar = getchar(start) + local startchar = start.char local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) if trace_kerns then logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) end end if b and #b > 0 then - local startchar = getchar(start) + local startchar = start.char local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) if trace_kerns then logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) @@ -967,7 +946,7 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) -- if a and a ~= 0 then -- local k = setkern(snext,factor,rlmode,a) -- if trace_kerns then - -- logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) + -- logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar)) -- end -- end -- if b and b ~= 0 then @@ -978,7 +957,7 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) elseif krn ~= 0 then local k = setkern(snext,factor,rlmode,krn) if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) + logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar)) end done = true end @@ -1033,13 +1012,13 @@ end -- itself. It is meant mostly for dealing with Urdu. function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements) - local char = getchar(start) + local char = start.char local replacement = replacements[char] if replacement then if trace_singles then logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement)) end - setfield(start,"char",replacement) + start.char = replacement return head, start, true else return head, start, false @@ -1068,9 +1047,9 @@ as less as needed but that would also make the code even more messy.</p> -- -- done -- elseif ignoremarks then -- repeat -- start x x m x x stop => start m --- local next = getnext(start) --- if not marks[getchar(next)] then --- local components = getfield(next,"components") +-- local next = start.next +-- if not marks[next.char] then +-- local components = next.components -- if components then -- probably not needed -- flush_node_list(components) -- end @@ -1080,8 +1059,8 @@ as less as needed but that would also make the code even more messy.</p> -- until next == stop -- else -- start x x x stop => start -- repeat --- local next = getnext(start) --- local components = getfield(next,"components") +-- local next = start.next +-- local components = next.components -- if components then -- probably not needed -- flush_node_list(components) -- end @@ -1105,8 +1084,8 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," ")) end while current do - if getid(current) == glyph_code then - local currentchar = getchar(current) + if current.id == glyph_code then + local currentchar = current.char local lookupname = subtables[1] -- only 1 local replacement = lookuphash[lookupname] if not replacement then @@ -1123,14 +1102,14 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo if trace_singles then logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement)) end - setfield(current,"char",replacement) + current.char = replacement end end return head, start, true elseif current == stop then break else - current = getnext(current) + current = current.next end end return head, start, false @@ -1145,7 +1124,7 @@ the match.</p> function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) -- local head, n = delete_till_stop(head,start,stop) - local startchar = getchar(start) + local startchar = start.char local subtables = currentlookup.subtables local lookupname = subtables[1] local replacements = lookuphash[lookupname] @@ -1188,8 +1167,8 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext local subtables = currentlookup.subtables local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue while current do - if getid(current) == glyph_code then -- is this check needed? - local currentchar = getchar(current) + if current.id == glyph_code then -- is this check needed? + local currentchar = current.char local lookupname = subtables[1] local alternatives = lookuphash[lookupname] if not alternatives then @@ -1204,7 +1183,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext if trace_alternatives then logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment) end - setfield(start,"char",choice) + start.char = choice else if trace_alternatives then logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment) @@ -1218,7 +1197,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext elseif current == stop then break else - current = getnext(current) + current = current.next end end return head, start, false @@ -1233,7 +1212,7 @@ assume rather stupid ligatures (no complex disc nodes).</p> --ldx]]-- function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) - local startchar = getchar(start) + local startchar = start.char local subtables = currentlookup.subtables local lookupname = subtables[1] local ligatures = lookuphash[lookupname] @@ -1248,20 +1227,20 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) end else - local s = getnext(start) + local s = start.next local discfound = false local last = stop local nofreplacements = 0 local skipmark = currentlookup.flags[1] while s do - local id = getid(s) + local id = s.id if id == disc_code then - s = getnext(s) + s = s.next discfound = true else - local schar = getchar(s) + local schar = s.char if skipmark and marks[schar] then -- marks - s = getnext(s) + s = s.next else local lg = ligatures[schar] if lg then @@ -1269,7 +1248,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, if s == stop then break else - s = getnext(s) + s = s.next end else break @@ -1286,7 +1265,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, if start == stop then logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2)) else - logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2)) + logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2)) end end head, start = toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound) @@ -1295,7 +1274,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, if start == stop then logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) else - logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop))) + logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char)) end end end @@ -1306,7 +1285,7 @@ end chainmores.gsub_ligature = chainprocs.gsub_ligature function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar = getchar(start) + local markchar = start.char if marks[markchar] then local subtables = currentlookup.subtables local lookupname = subtables[1] @@ -1315,14 +1294,14 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext markanchors = markanchors[markchar] end if markanchors then - local base = getprev(start) -- [glyph] [start=mark] - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then - local basechar = getchar(base) + local base = start.prev -- [glyph] [start=mark] + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then + local basechar = base.char if marks[basechar] then while true do - base = getprev(base) - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then - basechar = getchar(base) + base = base.prev + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then + basechar = base.char if not marks[basechar] then break end @@ -1370,7 +1349,7 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext end function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar = getchar(start) + local markchar = start.char if marks[markchar] then local subtables = currentlookup.subtables local lookupname = subtables[1] @@ -1379,14 +1358,14 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon markanchors = markanchors[markchar] end if markanchors then - local base = getprev(start) -- [glyph] [optional marks] [start=mark] - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then - local basechar = getchar(base) + local base = start.prev -- [glyph] [optional marks] [start=mark] + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then + local basechar = base.char if marks[basechar] then while true do - base = getprev(base) - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then - basechar = getchar(base) + base = base.prev + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then + basechar = base.char if not marks[basechar] then break end @@ -1399,7 +1378,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon end end -- todo: like marks a ligatures hash - local index = getattr(start,a_ligacomp) + local index = start[a_ligacomp] local baseanchors = descriptions[basechar].anchors if baseanchors then local baseanchors = baseanchors['baselig'] @@ -1439,9 +1418,9 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon end function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar = getchar(start) + local markchar = start.char if marks[markchar] then - -- local alreadydone = markonce and getattr(start,a_markmark) + -- local alreadydone = markonce and start[a_markmark] -- if not alreadydone then -- local markanchors = descriptions[markchar].anchors markanchors = markanchors and markanchors.mark local subtables = currentlookup.subtables @@ -1451,20 +1430,20 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext markanchors = markanchors[markchar] end if markanchors then - local base = getprev(start) -- [glyph] [basemark] [start=mark] - local slc = getattr(start,a_ligacomp) + local base = start.prev -- [glyph] [basemark] [start=mark] + local slc = start[a_ligacomp] if slc then -- a rather messy loop ... needs checking with husayni while base do - local blc = getattr(base,a_ligacomp) + local blc = base[a_ligacomp] if blc and blc ~= slc then - base = getprev(base) + base = base.prev else break end end end - if base and getid(base) == glyph_code and getfont(base) == currentfont and getsubtype(base)<256 then -- subtype test can go - local basechar = getchar(base) + if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then -- subtype test can go + local basechar = base.char local baseanchors = descriptions[basechar].anchors if baseanchors then baseanchors = baseanchors['basemark'] @@ -1504,9 +1483,9 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext end function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local alreadydone = cursonce and getattr(start,a_cursbase) + local alreadydone = cursonce and start[a_cursbase] if not alreadydone then - local startchar = getchar(start) + local startchar = start.char local subtables = currentlookup.subtables local lookupname = subtables[1] local exitanchors = lookuphash[lookupname] @@ -1520,12 +1499,12 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar)) end else - local nxt = getnext(start) - while not done and nxt and getid(nxt) == glyph_code and getfont(nxt) == currentfont and getsubtype(nxt)<256 do - local nextchar = getchar(nxt) + local nxt = start.next + while not done and nxt and nxt.id == glyph_code and nxt.font == currentfont and nxt.subtype<256 do + local nextchar = nxt.char if marks[nextchar] then -- should not happen (maybe warning) - nxt = getnext(nxt) + nxt = nxt.next else local entryanchors = descriptions[nextchar] if entryanchors then @@ -1560,7 +1539,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l return head, start, done else if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone) + logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) end return head, start, false end @@ -1570,7 +1549,7 @@ end function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) -- untested .. needs checking for the new model - local startchar = getchar(start) + local startchar = start.char local subtables = currentlookup.subtables local lookupname = subtables[1] local kerns = lookuphash[lookupname] @@ -1591,9 +1570,9 @@ chainmores.gpos_single = chainprocs.gpos_single -- okay? -- when machines become faster i will make a shared function function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) - local snext = getnext(start) + local snext = start.next if snext then - local startchar = getchar(start) + local startchar = start.char local subtables = currentlookup.subtables local lookupname = subtables[1] local kerns = lookuphash[lookupname] @@ -1603,12 +1582,12 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look local lookuptype = lookuptypes[lookupname] local prev, done = start, false local factor = tfmdata.parameters.factor - while snext and getid(snext) == glyph_code and getfont(snext) == currentfont and getsubtype(snext)<256 do - local nextchar = getchar(snext) + while snext and snext.id == glyph_code and snext.font == currentfont and snext.subtype<256 do + local nextchar = snext.char local krn = kerns[nextchar] if not krn and marks[nextchar] then prev = snext - snext = getnext(snext) + snext = snext.next else if not krn then -- skip @@ -1616,14 +1595,14 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look if lookuptype == "pair" then local a, b = krn[2], krn[3] if a and #a > 0 then - local startchar = getchar(start) + local startchar = start.char local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) if trace_kerns then logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) end end if b and #b > 0 then - local startchar = getchar(start) + local startchar = start.char local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) if trace_kerns then logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) @@ -1635,7 +1614,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look if a and a ~= 0 then local k = setkern(snext,factor,rlmode,a) if trace_kerns then - logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar)) + logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) end end if b and b ~= 0 then @@ -1646,7 +1625,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look elseif krn ~= 0 then local k = setkern(snext,factor,rlmode,krn) if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar)) + logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) end done = true end @@ -1678,12 +1657,6 @@ local function show_skip(kind,chainname,char,ck,class) end end -local quit_on_no_replacement = true - -directives.register("otf.chain.quitonnoreplacement",function(value) -- maybe per font - quit_on_no_replacement = value -end) - local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash) -- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6] local flags = sequence.flags @@ -1704,7 +1677,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq -- f..l = mid string if s == 1 then -- never happens - match = getid(current) == glyph_code and getfont(current) == currentfont and getsubtype(current)<256 and seq[1][getchar(current)] + match = current.id == glyph_code and current.font == currentfont and current.subtype<256 and seq[1][current.char] else -- maybe we need a better space check (maybe check for glue or category or combination) -- we cannot optimize for n=2 because there can be disc nodes @@ -1719,13 +1692,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq -- match = true else local n = f + 1 - last = getnext(last) + last = last.next while n <= l do if last then - local id = getid(last) + local id = last.id if id == glyph_code then - if getfont(last) == currentfont and getsubtype(last)<256 then - local char = getchar(last) + if last.font == currentfont and last.subtype<256 then + local char = last.char local ccd = descriptions[char] if ccd then local class = ccd.class @@ -1734,10 +1707,10 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if trace_skips then show_skip(kind,chainname,char,ck,class) end - last = getnext(last) + last = last.next elseif seq[n][char] then if n < l then - last = getnext(last) + last = last.next end n = n + 1 else @@ -1753,7 +1726,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq break end elseif id == disc_code then - last = getnext(last) + last = last.next else match = false break @@ -1767,15 +1740,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq end -- before if match and f > 1 then - local prev = getprev(start) + local prev = start.prev if prev then local n = f-1 while n >= 1 do if prev then - local id = getid(prev) + local id = prev.id if id == glyph_code then - if getfont(prev) == currentfont and getsubtype(prev)<256 then -- normal char - local char = getchar(prev) + if prev.font == currentfont and prev.subtype<256 then -- normal char + local char = prev.char local ccd = descriptions[char] if ccd then local class = ccd.class @@ -1806,7 +1779,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq match = false break end - prev = getprev(prev) + prev = prev.prev elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces n = n -1 else @@ -1827,16 +1800,16 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq end -- after if match and s > l then - local current = last and getnext(last) + local current = last and last.next if current then -- removed optimization for s-l == 1, we have to deal with marks anyway local n = l + 1 while n <= s do if current then - local id = getid(current) + local id = current.id if id == glyph_code then - if getfont(current) == currentfont and getsubtype(current)<256 then -- normal char - local char = getchar(current) + if current.font == currentfont and current.subtype<256 then -- normal char + local char = current.char local ccd = descriptions[char] if ccd then local class = ccd.class @@ -1867,7 +1840,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq match = false break end - current = getnext(current) + current = current.next elseif seq[n][32] then n = n + 1 else @@ -1891,7 +1864,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq -- ck == currentcontext if trace_contexts then local rule, lookuptype, f, l = ck[1], ck[2], ck[4], ck[5] - local char = getchar(start) + local char = start.char if ck[9] then logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a", cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10]) @@ -1926,12 +1899,12 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq repeat if skipped then while true do - local char = getchar(start) + local char = start.char local ccd = descriptions[char] if ccd then local class = ccd.class if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - start = getnext(start) + start = start.next else break end @@ -1965,7 +1938,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq end end if start then - start = getnext(start) + start = start.next else -- weird end @@ -1976,7 +1949,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if replacements then head, start, done = chainprocs.reversesub(head,start,last,kind,chainname,ck,lookuphash,replacements) -- sequence else - done = quit_on_no_replacement -- can be meant to be skipped / quite inconsistent in fonts + done = true -- can be meant to be skipped if trace_contexts then logprocess("%s: skipping match",cref(kind,chainname)) end @@ -2126,12 +2099,12 @@ end -- if ok then -- done = true -- end --- if start then start = getnext(start) end +-- if start then start = start.next end -- else --- start = getnext(start) +-- start = start.next -- end -- else --- start = getnext(start) +-- start = start.next -- end -- there will be a new direction parser (pre-parsed etc) @@ -2153,8 +2126,6 @@ local function featuresprocessor(head,font,attr) return head, false end - head = tonut(head) - if trace_steps then checkstep(head) end @@ -2186,8 +2157,6 @@ local function featuresprocessor(head,font,attr) -- Keeping track of the headnode is needed for devanagari (I generalized it a bit -- so that multiple cases are also covered.) - -- todo: retain prev - for s=1,#datasets do local dataset = datasets[s] featurevalue = dataset[1] -- todo: pass to function instead of using a global @@ -2206,10 +2175,10 @@ local function featuresprocessor(head,font,attr) -- we need to get rid of this slide! probably no longer needed in latest luatex local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo while start do - local id = getid(start) + local id = start.id if id == glyph_code then - if getfont(start) == font and getsubtype(start) < 256 then - local a = getattr(start,0) + if start.font == font and start.subtype<256 then + local a = start[0] if a then a = a == attr else @@ -2220,7 +2189,7 @@ local function featuresprocessor(head,font,attr) local lookupname = subtables[i] local lookupcache = lookuphash[lookupname] if lookupcache then - local lookupmatch = lookupcache[getchar(start)] + local lookupmatch = lookupcache[start.char] if lookupmatch then head, start, success = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if success then @@ -2231,15 +2200,15 @@ local function featuresprocessor(head,font,attr) report_missing_cache(typ,lookupname) end end - if start then start = getprev(start) end + if start then start = start.prev end else - start = getprev(start) + start = start.prev end else - start = getprev(start) + start = start.prev end else - start = getprev(start) + start = start.prev end end else @@ -2259,16 +2228,16 @@ local function featuresprocessor(head,font,attr) local head = start local done = false while start do - local id = getid(start) - if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then - local a = getattr(start,0) + local id = start.id + if id == glyph_code and start.font == font and start.subtype <256 then + local a = start[0] if a then - a = (a == attr) and (not attribute or getattr(start,a_state) == attribute) + a = (a == attr) and (not attribute or start[a_state] == attribute) else - a = not attribute or getattr(start,a_state) == attribute + a = not attribute or start[a_state] == attribute end if a then - local lookupmatch = lookupcache[getchar(start)] + local lookupmatch = lookupcache[start.char] if lookupmatch then -- sequence kan weg local ok @@ -2277,12 +2246,12 @@ local function featuresprocessor(head,font,attr) done = true end end - if start then start = getnext(start) end + if start then start = start.next end else - start = getnext(start) + start = start.next end else - start = getnext(start) + start = start.next end end if done then @@ -2292,19 +2261,19 @@ local function featuresprocessor(head,font,attr) end local function kerndisc(disc) -- we can assume that prev and next are glyphs - local prev = getprev(disc) - local next = getnext(disc) + local prev = disc.prev + local next = disc.next if prev and next then - setfield(prev,"next",next) - -- setfield(next,"prev",prev) - local a = getattr(prev,0) + prev.next = next + -- next.prev = prev + local a = prev[0] if a then - a = (a == attr) and (not attribute or getattr(prev,a_state) == attribute) + a = (a == attr) and (not attribute or prev[a_state] == attribute) else - a = not attribute or getattr(prev,a_state) == attribute + a = not attribute or prev[a_state] == attribute end if a then - local lookupmatch = lookupcache[getchar(prev)] + local lookupmatch = lookupcache[prev.char] if lookupmatch then -- sequence kan weg local h, d, ok = handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) @@ -2314,24 +2283,24 @@ local function featuresprocessor(head,font,attr) end end end - setfield(prev,"next",disc) - -- setfield(next,"prev",disc) + prev.next = disc + -- next.prev = disc end return next end while start do - local id = getid(start) + local id = start.id if id == glyph_code then - if getfont(start) == font and getsubtype(start) < 256 then - local a = getattr(start,0) + if start.font == font and start.subtype<256 then + local a = start[0] if a then - a = (a == attr) and (not attribute or getattr(start,a_state) == attribute) + a = (a == attr) and (not attribute or start[a_state] == attribute) else - a = not attribute or getattr(start,a_state) == attribute + a = not attribute or start[a_state] == attribute end if a then - local lookupmatch = lookupcache[getchar(start)] + local lookupmatch = lookupcache[start.char] if lookupmatch then -- sequence kan weg local ok @@ -2340,39 +2309,39 @@ local function featuresprocessor(head,font,attr) success = true end end - if start then start = getnext(start) end + if start then start = start.next end else - start = getnext(start) + start = start.next end else - start = getnext(start) + start = start.next end elseif id == disc_code then -- mostly for gsub - if getsubtype(start) == discretionary_code then - local pre = getfield(start,"pre") + if start.subtype == discretionary_code then + local pre = start.pre if pre then local new = subrun(pre) - if new then setfield(start,"pre",new) end + if new then start.pre = new end end - local post = getfield(start,"post") + local post = start.post if post then local new = subrun(post) - if new then setfield(start,"post",new) end + if new then start.post = new end end - local replace = getfield(start,"replace") + local replace = start.replace if replace then local new = subrun(replace) - if new then setfield(start,"replace",new) end + if new then start.replace = new end end elseif typ == "gpos_single" or typ == "gpos_pair" then kerndisc(start) end - start = getnext(start) + start = start.next elseif id == whatsit_code then -- will be function - local subtype = getsubtype(start) + local subtype = start.subtype if subtype == dir_code then - local dir = getfield(start,"dir") + local dir = start.dir if dir == "+TRT" or dir == "+TLT" then topstack = topstack + 1 dirstack[topstack] = dir @@ -2391,7 +2360,7 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir) end elseif subtype == localpar_code then - local dir = getfield(start,"dir") + local dir = start.dir if dir == "TRT" then rlparmode = -1 elseif dir == "TLT" then @@ -2405,11 +2374,11 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode) end end - start = getnext(start) + start = start.next elseif id == math_code then - start = getnext(end_of_math(start)) + start = end_of_math(start).next else - start = getnext(start) + start = start.next end end end @@ -2420,20 +2389,20 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then local head = start local done = false while start do - local id = getid(start) - if id == glyph_code and getfont(start) == font and getsubtype(start) < 256 then - local a = getattr(start,0) + local id = start.id + if id == glyph_code and start.id == font and start.subtype <256 then + local a = start[0] if a then - a = (a == attr) and (not attribute or getattr(start,a_state) == attribute) + a = (a == attr) and (not attribute or start[a_state] == attribute) else - a = not attribute or getattr(start,a_state) == attribute + a = not attribute or start[a_state] == attribute end if a then for i=1,ns do local lookupname = subtables[i] local lookupcache = lookuphash[lookupname] if lookupcache then - local lookupmatch = lookupcache[getchar(start)] + local lookupmatch = lookupcache[start.char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable local ok @@ -2450,12 +2419,12 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then report_missing_cache(typ,lookupname) end end - if start then start = getnext(start) end + if start then start = start.next end else - start = getnext(start) + start = start.next end else - start = getnext(start) + start = start.next end end if done then @@ -2465,23 +2434,23 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then end local function kerndisc(disc) -- we can assume that prev and next are glyphs - local prev = getprev(disc) - local next = getnext(disc) + local prev = disc.prev + local next = disc.next if prev and next then - setfield(prev,"next",next) - -- setfield(next,"prev",prev) - local a = getattr(prev,0) + prev.next = next + -- next.prev = prev + local a = prev[0] if a then - a = (a == attr) and (not attribute or getattr(prev,a_state) == attribute) + a = (a == attr) and (not attribute or prev[a_state] == attribute) else - a = not attribute or getattr(prev,a_state) == attribute + a = not attribute or prev[a_state] == attribute end if a then for i=1,ns do local lookupname = subtables[i] local lookupcache = lookuphash[lookupname] if lookupcache then - local lookupmatch = lookupcache[getchar(prev)] + local lookupmatch = lookupcache[prev.char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable local h, d, ok = handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) @@ -2495,28 +2464,28 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then end end end - setfield(prev,"next",disc) - -- setfield(next,"prev",disc) + prev.next = disc + -- next.prev = disc end return next end while start do - local id = getid(start) + local id = start.id if id == glyph_code then - if getfont(start) == font and getsubtype(start) < 256 then - local a = getattr(start,0) + if start.font == font and start.subtype<256 then + local a = start[0] if a then - a = (a == attr) and (not attribute or getattr(start,a_state) == attribute) + a = (a == attr) and (not attribute or start[a_state] == attribute) else - a = not attribute or getattr(start,a_state) == attribute + a = not attribute or start[a_state] == attribute end if a then for i=1,ns do local lookupname = subtables[i] local lookupcache = lookuphash[lookupname] if lookupcache then - local lookupmatch = lookupcache[getchar(start)] + local lookupmatch = lookupcache[start.char] if lookupmatch then -- we could move all code inline but that makes things even more unreadable local ok @@ -2533,39 +2502,39 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then report_missing_cache(typ,lookupname) end end - if start then start = getnext(start) end + if start then start = start.next end else - start = getnext(start) + start = start.next end else - start = getnext(start) + start = start.next end elseif id == disc_code then -- mostly for gsub - if getsubtype(start) == discretionary_code then - local pre = getfield(start,"pre") + if start.subtype == discretionary_code then + local pre = start.pre if pre then local new = subrun(pre) - if new then setfield(start,"pre",new) end + if new then start.pre = new end end - local post = getfield(start,"post") + local post = start.post if post then local new = subrun(post) - if new then setfield(start,"post",new) end + if new then start.post = new end end - local replace = getfield(start,"replace") + local replace = start.replace if replace then local new = subrun(replace) - if new then setfield(start,"replace",new) end + if new then start.replace = new end end elseif typ == "gpos_single" or typ == "gpos_pair" then kerndisc(start) end - start = getnext(start) + start = start.next elseif id == whatsit_code then - local subtype = getsubtype(start) + local subtype = start.subtype if subtype == dir_code then - local dir = getfield(start,"dir") + local dir = start.dir if dir == "+TRT" or dir == "+TLT" then topstack = topstack + 1 dirstack[topstack] = dir @@ -2584,7 +2553,7 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir) end elseif subtype == localpar_code then - local dir = getfield(start,"dir") + local dir = start.dir if dir == "TRT" then rlparmode = -1 elseif dir == "TLT" then @@ -2597,11 +2566,11 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode) end end - start = getnext(start) + start = start.next elseif id == math_code then - start = getnext(end_of_math(start)) + start = end_of_math(start).next else - start = getnext(start) + start = start.next end end end @@ -2613,9 +2582,6 @@ elseif typ == "gpos_single" or typ == "gpos_pair" then registerstep(head) end end - - head = tonode(head) - return head, done end diff --git a/tex/context/base/font-ott.lua b/tex/context/base/font-ott.lua index 1e2309056..e3aacd0d1 100644 --- a/tex/context/base/font-ott.lua +++ b/tex/context/base/font-ott.lua @@ -42,7 +42,6 @@ local scripts = allocate { ['cprt'] = 'cypriot syllabary', ['cyrl'] = 'cyrillic', ['deva'] = 'devanagari', - ['dev2'] = 'devanagari variant 2', ['dsrt'] = 'deseret', ['ethi'] = 'ethiopic', ['geor'] = 'georgian', @@ -68,7 +67,6 @@ local scripts = allocate { ['linb'] = 'linear b', ['math'] = 'mathematical alphanumeric symbols', ['mlym'] = 'malayalam', - ['mlm2'] = 'malayalam variant 2', ['mong'] = 'mongolian', ['musc'] = 'musical symbols', ['mymr'] = 'myanmar', @@ -633,7 +631,6 @@ local features = allocate { ['js..'] = 'justification ..', ["dv.."] = "devanagari ..", - ["ml.."] = "malayalam ..", } local baselines = allocate { diff --git a/tex/context/base/font-otx.lua b/tex/context/base/font-otx.lua index b7d2ae0bc..f39045223 100644 --- a/tex/context/base/font-otx.lua +++ b/tex/context/base/font-otx.lua @@ -30,29 +30,15 @@ analyzers.methods = methods local a_state = attributes.private('state') -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar - -local setattr = nuts.setattr - -local traverse_id = nuts.traverse_id -local traverse_node_list = nuts.traverse -local end_of_math = nuts.end_of_math - local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local disc_code = nodecodes.disc local math_code = nodecodes.math +local traverse_id = node.traverse_id +local traverse_node_list = node.traverse +local end_of_math = node.end_of_math + local fontdata = fonts.hashes.identifiers local categories = characters and characters.categories or { } -- sorry, only in context local chardata = characters and characters.data @@ -109,61 +95,60 @@ analyzers.useunicodemarks = false -- todo: analyzers per script/lang, cross font, so we need an font id hash -> script -- e.g. latin -> hyphenate, arab -> 1/2/3 analyze -- its own namespace -function analyzers.setstate(head,font) -- we can skip math +function analyzers.setstate(head,font) local useunicodemarks = analyzers.useunicodemarks local tfmdata = fontdata[font] local descriptions = tfmdata.descriptions local first, last, current, n, done = nil, nil, head, 0, false -- maybe make n boolean - current = tonut(current) while current do - local id = getid(current) - if id == glyph_code and getfont(current) == font then + local id = current.id + if id == glyph_code and current.font == font then done = true - local char = getchar(current) + local char = current.char local d = descriptions[char] if d then if d.class == "mark" then done = true - setattr(current,a_state,s_mark) + current[a_state] = s_mark elseif useunicodemarks and categories[char] == "mn" then done = true - setattr(current,a_state,s_mark) + current[a_state] = s_mark elseif n == 0 then first, last, n = current, current, 1 - setattr(current,a_state,s_init) + current[a_state] = s_init else last, n = current, n+1 - setattr(current,a_state,s_medi) + current[a_state] = s_medi end else -- finish if first and first == last then - setattr(last,a_state,s_isol) + last[a_state] = s_isol elseif last then - setattr(last,a_state,s_fina) + last[a_state] = s_fina end first, last, n = nil, nil, 0 end elseif id == disc_code then -- always in the middle - setattr(current,a_state,s_medi) + current[a_state] = s_medi last = current else -- finish if first and first == last then - setattr(last,a_state,s_isol) + last[a_state] = s_isol elseif last then - setattr(last,a_state,s_fina) + last[a_state] = s_fina end first, last, n = nil, nil, 0 if id == math_code then current = end_of_math(current) end end - current = getnext(current) + current = current.next end if first and first == last then - setattr(last,a_state,s_isol) + last[a_state] = s_isol elseif last then - setattr(last,a_state,s_fina) + last[a_state] = s_fina end return head, done end @@ -224,7 +209,7 @@ methods.latn = analyzers.setstate local arab_warned = { } local function warning(current,what) - local char = getchar(current) + local char = current.char if not arab_warned[char] then log.report("analyze","arab: character %C has no %a class",char,what) arab_warned[char] = true @@ -276,95 +261,94 @@ function methods.arab(head,font,attr) local first, last = nil, nil local c_first, c_last = nil, nil local current, done = head, false - current = tonut(current) while current do - local id = getid(current) - if id == glyph_code and getfont(current) == font and getsubtype(current)<256 and not getattr(current,a_state) then + local id = current.id + if id == glyph_code and current.font == font and current.subtype<256 and not current[a_state] then done = true - local char = getchar(current) + local char = current.char local classifier = classifiers[char] if not classifier then if last then if c_last == s_medi or c_last == s_fina then - setattr(last,a_state,s_fina) + last[a_state] = s_fina else warning(last,"fina") - setattr(last,a_state,s_error) + last[a_state] = s_error end first, last = nil, nil elseif first then if c_first == s_medi or c_first == s_fina then - setattr(first,a_state,s_isol) + first[a_state] = s_isol else warning(first,"isol") - setattr(first,a_state,s_error) + first[a_state] = s_error end first = nil end elseif classifier == s_mark then - setattr(current,a_state,s_mark) + current[a_state] = s_mark elseif classifier == s_isol then if last then if c_last == s_medi or c_last == s_fina then - setattr(last,a_state,s_fina) + last[a_state] = s_fina else warning(last,"fina") - setattr(last,a_state,s_error) + last[a_state] = s_error end first, last = nil, nil elseif first then if c_first == s_medi or c_first == s_fina then - setattr(first,a_state,s_isol) + first[a_state] = s_isol else warning(first,"isol") - setattr(first,a_state,s_error) + first[a_state] = s_error end first = nil end - setattr(current,a_state,s_isol) + current[a_state] = s_isol elseif classifier == s_medi then if first then last = current c_last = classifier - setattr(current,a_state,s_medi) + current[a_state] = s_medi else - setattr(current,a_state,s_init) + current[a_state] = s_init first = current c_first = classifier end elseif classifier == s_fina then if last then - if getattr(last,a_state) ~= s_init then - setattr(last,a_state,s_medi) + if last[a_state] ~= s_init then + last[a_state] = s_medi end - setattr(current,a_state,s_fina) + current[a_state] = s_fina first, last = nil, nil elseif first then - -- if getattr(first,a_state) ~= s_init then + -- if first[a_state] ~= s_init then -- -- needs checking - -- setattr(first,a_state,s_medi) + -- first[a_state] = s_medi -- end - setattr(current,a_state,s_fina) + current[a_state] = s_fina first = nil else - setattr(current,a_state,s_isol) + current[a_state] = s_isol end else -- classifier == s_rest - setattr(current,a_state,s_rest) + current[a_state] = s_rest if last then if c_last == s_medi or c_last == s_fina then - setattr(last,a_state,s_fina) + last[a_state] = s_fina else warning(last,"fina") - setattr(last,a_state,s_error) + last[a_state] = s_error end first, last = nil, nil elseif first then if c_first == s_medi or c_first == s_fina then - setattr(first,a_state,s_isol) + first[a_state] = s_isol else warning(first,"isol") - setattr(first,a_state,s_error) + first[a_state] = s_error end first = nil end @@ -372,18 +356,18 @@ function methods.arab(head,font,attr) else if last then if c_last == s_medi or c_last == s_fina then - setattr(last,a_state,s_fina) + last[a_state] = s_fina else warning(last,"fina") - setattr(last,a_state,s_error) + last[a_state] = s_error end first, last = nil, nil elseif first then if c_first == s_medi or c_first == s_fina then - setattr(first,a_state,s_isol) + first[a_state] = s_isol else warning(first,"isol") - setattr(first,a_state,s_error) + first[a_state] = s_error end first = nil end @@ -391,21 +375,21 @@ function methods.arab(head,font,attr) current = end_of_math(current) end end - current = getnext(current) + current = current.next end if last then if c_last == s_medi or c_last == s_fina then - setattr(last,a_state,s_fina) + last[a_state] = s_fina else warning(last,"fina") - setattr(last,a_state,s_error) + last[a_state] = s_error end elseif first then if c_first == s_medi or c_first == s_fina then - setattr(first,a_state,s_isol) + first[a_state] = s_isol else warning(first,"isol") - setattr(first,a_state,s_error) + first[a_state] = s_error end end return head, done diff --git a/tex/context/base/font-pat.lua b/tex/context/base/font-pat.lua index 049853796..9733c9ada 100644 --- a/tex/context/base/font-pat.lua +++ b/tex/context/base/font-pat.lua @@ -38,7 +38,7 @@ local report = patches.report -- library) the palatino arabic fonts don't have the mkmk features properly -- set up. -register("after","rehash features","^palatino.*arabic", function (data,filename) +register("after","rehash features","^palatino.*arabic", function patch(data,filename) local gpos = data.gpos if gpos then for k=1,#gpos do diff --git a/tex/context/base/font-pre.mkiv b/tex/context/base/font-pre.mkiv index fc6eb289e..c404771fd 100644 --- a/tex/context/base/font-pre.mkiv +++ b/tex/context/base/font-pre.mkiv @@ -170,24 +170,6 @@ kern=yes] \definefontfeature - [malayalam-one] - [mode=node, - language=dflt, - script=mlym, - akhn=yes, - blwf=yes, - half=yes, - pres=yes, - blws=yes, - psts=yes, - haln=no] - -\definefontfeature - [malayalam-two] - [malayalam-one] - [script=mlm2] - -\definefontfeature [jamoforms] [ljmo=yes, tjmo=yes, diff --git a/tex/context/base/font-sol.lua b/tex/context/base/font-sol.lua index a41e4a679..9ccfd0588 100644 --- a/tex/context/base/font-sol.lua +++ b/tex/context/base/font-sol.lua @@ -48,41 +48,19 @@ local v_split = variables.split local settings_to_array = utilities.parsers.settings_to_array local settings_to_hash = utilities.parsers.settings_to_hash -local tasks = nodes.tasks - -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getlist = nuts.getlist - -local find_node_tail = nuts.tail -local free_node = nuts.free -local free_nodelist = nuts.flush_list -local copy_nodelist = nuts.copy_list -local traverse_nodes = nuts.traverse -local traverse_ids = nuts.traverse_id -local hpack_nodes = nuts.hpack -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local protect_glyphs = nuts.protect_glyphs - -local repack_hlist = nuts.repackhlist - +local find_node_tail = node.tail or node.slide +local free_node = node.free +local free_nodelist = node.flush_list +local copy_nodelist = node.copy_list +local traverse_nodes = node.traverse +local traverse_ids = node.traverse_id +local protect_glyphs = nodes.handlers.protectglyphs or node.protect_glyphs +local hpack_nodes = node.hpack +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local repack_hlist = nodes.repackhlist local nodes_to_utf = nodes.listtoutf ------ protect_glyphs = nodes.handlers.protectglyphs - local setnodecolor = nodes.tracers.colors.set local nodecodes = nodes.nodecodes @@ -101,7 +79,8 @@ local localpar_code = whatsitcodes.localpar local dir_code = whatsitcodes.dir local userdefined_code = whatsitcodes.userdefined -local nodepool = nuts.pool +local nodepool = nodes.pool +local tasks = nodes.tasks local usernodeids = nodepool.userids local new_textdir = nodepool.textdir @@ -111,7 +90,7 @@ local new_leftskip = nodepool.leftskip local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming ------ process_characters = nodes.handlers.characters +local process_characters = nodes.handlers.characters local inject_kerns = nodes.injections.handler local fonthashes = fonts.hashes @@ -338,12 +317,11 @@ end) function splitters.split(head) -- quite fast - head = tonut(head) local current, done, rlmode, start, stop, attribute = head, false, false, nil, nil, 0 cache, max_less, max_more = { }, 0, 0 local function flush() -- we can move this - local font = getfont(start) - local last = getnext(stop) + local font = start.font + local last = stop.next local list = last and copy_nodelist(start,last) or copy_nodelist(start) local n = #cache + 1 if encapsulate then @@ -354,18 +332,18 @@ function splitters.split(head) else local current = start while true do - setattr(current,a_word,n) + current[a_word] = n if current == stop then break else - current = getnext(current) + current = current.next end end end if rlmode == "TRT" or rlmode == "+TRT" then local dirnode = new_textdir("+TRT") - setfield(list,"prev",dirnode) - setfield(dirnode,"next",list) + list.prev = dirnode + dirnode.next = list list = dirnode end local c = { @@ -386,11 +364,11 @@ function splitters.split(head) start, stop, done = nil, nil, true end while current do -- also nextid - local next = getnext(current) - local id = getid(current) + local next = current.next + local id = current.id if id == glyph_code then - if getsubtype(current) < 256 then - local a = getattr(current,a_split) + if current.subtype < 256 then + local a = current[a_split] if not a then start, stop = nil, nil elseif not start then @@ -406,7 +384,7 @@ function splitters.split(head) if start then flush() end - elseif start and next and getid(next) == glyph_code and getsubtype(next) < 256 then + elseif start and next and next.id == glyph_code and next.subtype < 256 then -- beware: we can cross future lines stop = next else @@ -416,9 +394,9 @@ function splitters.split(head) if start then flush() end - local subtype = getsubtype(current) + local subtype = current.subtype if subtype == dir_code or subtype == localpar_code then - rlmode = getfield(current,"dir") + rlmode = current.dir end else if start then @@ -432,17 +410,17 @@ function splitters.split(head) end nofparagraphs = nofparagraphs + 1 nofwords = nofwords + #cache - return tonode(head), done + return head, done end local function collect_words(list) -- can be made faster for attributes local words, w, word = { }, 0, nil if encapsulate then for current in traverse_ids(whatsit_code,list) do - if getsubtype(current) == userdefined_code then -- hm - local user_id = getfield(current,"user_id") + if current.subtype == userdefined_code then -- hm + local user_id = current.user_id if user_id == splitter_one then - word = { getfield(current,"value"), current, current } + word = { current.value, current, current } w = w + 1 words[w] = word elseif user_id == splitter_two then @@ -458,9 +436,9 @@ local function collect_words(list) -- can be made faster for attributes local current, first, last, index = list, nil, nil, nil while current do -- todo: disc and kern - local id = getid(current) + local id = current.id if id == glyph_code or id == disc_code then - local a = getattr(current,a_word) + local a = current[a_word] if a then if a == index then -- same word @@ -493,7 +471,7 @@ local function collect_words(list) -- can be made faster for attributes report_splitters("skipped: %C",current.char) end end - elseif id == kern_code and (getsubtype(current) == fontkern_code or getattr(current,a_fontkern)) then + elseif id == kern_code and (current.subtype == fontkern_code or current[a_fontkern]) then if first then last = current else @@ -511,7 +489,7 @@ local function collect_words(list) -- can be made faster for attributes end end end - current = getnext(current) + current = current.next end if index then w = w + 1 @@ -542,8 +520,8 @@ local function doit(word,list,best,width,badness,line,set,listdir) if found then local h, t if encapsulate then - h = getnext(word[2]) -- head of current word - t = getprev(word[3]) -- tail of current word + h = word[2].next -- head of current word + t = word[3].prev -- tail of current word else h = word[2] t = word[3] @@ -558,7 +536,7 @@ local function doit(word,list,best,width,badness,line,set,listdir) ok = true break else - c = getnext(c) + c = c.next end end if not ok then @@ -577,20 +555,19 @@ local function doit(word,list,best,width,badness,line,set,listdir) local first = copy_nodelist(original) if not trace_colors then for n in traverse_nodes(first) do -- maybe fast force so no attr needed - setattr(n,0,featurenumber) -- this forces dynamics + n[0] = featurenumber -- this forces dynamics end elseif set == "less" then for n in traverse_nodes(first) do setnodecolor(n,"font:isol") -- yellow - setattr(n,0,featurenumber) + n[0] = featurenumber end else for n in traverse_nodes(first) do setnodecolor(n,"font:medi") -- green - setattr(n,0,featurenumber) + n[0] = featurenumber end end -first = tonode(first) local font = found.font local setdynamics = setfontdynamics[font] if setdynamics then @@ -602,21 +579,20 @@ first = tonode(first) report_solutions("fatal error, no dynamics for font %a",font) end first = inject_kerns(first) -first = tonut(first) - if getid(first) == whatsit_code then + if first.id == whatsit_code then local temp = first - first = getnext(first) + first = first.next free_node(temp) end local last = find_node_tail(first) -- replace [u]h->t by [u]first->last - local prev = getprev(h) - local next = getnext(t) - setfield(prev,"next",first) - setfield(first,"prev",prev) + local prev = h.prev + local next = t.next + prev.next = first + first.prev = prev if next then - setfield(last,"next",next) - setfield(next,"prev",last) + last.next = next + next.prev = last end -- check new pack local temp, b = repack_hlist(list,width,'exactly',listdir) @@ -625,22 +601,22 @@ first = tonut(first) report_optimizers("line %a, badness before %a, after %a, criterium %a, verdict %a",line,badness,b,criterium,"quit") end -- remove last insert - setfield(prev,"next",h) - setfield(h,"prev",prev) + prev.next = h + h.prev = prev if next then - setfield(t,"next",next) - setfield(next,"prev",t) + t.next = next + next.prev = t else - setfield(t,"next",nil) + t.next = nil end - setfield(last,"next",nil) + last.next = nil free_nodelist(first) else if trace_optimize then report_optimizers("line %a, badness before: %a, after %a, criterium %a, verdict %a",line,badness,b,criterium,"continue") end -- free old h->t - setfield(t,"next",nil) + t.next = nil free_nodelist(h) -- somhow fails if not encapsulate then word[2] = first @@ -721,9 +697,9 @@ variants[v_random] = function(words,list,best,width,badness,line,set,listdir) end local function show_quality(current,what,line) - local set = getfield(current,"glue_set") - local sign = getfield(current,"glue_sign") - local order = getfield(current,"glue_order") + local set = current.glue_set + local sign = current.glue_sign + local order = current.glue_order local amount = set * ((sign == 2 and -1) or 1) report_optimizers("line %a, category %a, amount %a, set %a, sign %a, how %a, order %a",line,what,amount,set,sign,how,order) end @@ -743,25 +719,20 @@ function splitters.optimize(head) math.setrandomseedi(randomseed) randomseed = nil end - local line = 0 - local tex_hbadness = tex.hbadness - local tex_hfuzz = tex.hfuzz - tex.hbadness = 10000 - tex.hfuzz = number.maxdimen + local line = 0 + local tex_hbadness, tex_hfuzz = tex.hbadness, tex.hfuzz + tex.hbadness, tex.hfuzz = 10000, number.maxdimen if trace_optimize then report_optimizers("preroll %a, variant %a, criterium %a, cache size %a",preroll,variant,criterium,nc) end - for current in traverse_ids(hlist_code,tonut(head)) do + for current in traverse_ids(hlist_code,head) do + -- report_splitters("before: [%s] => %s",current.dir,nodes.tosequence(current.list,nil)) line = line + 1 - local sign = getfield(current,"glue_sign") - local dir = getfield(current,"dir") - local width = getfield(current,"width") - local list = getlist(current) - if not encapsulate and getid(list) == glyph_code then + local sign, dir, list, width = current.glue_sign, current.dir, current.list, current.width + if not encapsulate and list.id == glyph_code then -- nasty .. we always assume a prev being there .. future luatex will always have a leftskip set - -- is this assignment ok ? .. needs checking - list = insert_node_before(list,list,new_leftskip(0)) -- new_glue(0) - setfield(current,"list",list) + -- current.list, list = insert_node_before(list,list,new_glue(0)) + current.list, list = insert_node_before(list,list,new_leftskip(0)) end local temp, badness = repack_hlist(list,width,'exactly',dir) -- it would be nice if the badness was stored in the node if badness > 0 then @@ -821,7 +792,7 @@ function splitters.optimize(head) local words = collect_words(list) for best=lastbest or 1,max do local temp, done, changes, b = optimize(words,list,best,width,badness,line,set,dir) - setfield(current,"list",temp) + current.list = temp if trace_optimize then report_optimizers("line %a, alternative %a, changes %a, badness %a",line,best,changes,b) end @@ -839,16 +810,15 @@ function splitters.optimize(head) end end -- we pack inside the outer hpack and that way keep the original wd/ht/dp as bonus - local list = hpack_nodes(getlist(current),width,'exactly',listdir) - setfield(current,"list",list) + current.list = hpack_nodes(current.list,width,'exactly',listdir) + -- report_splitters("after: [%s] => %s",temp.dir,nodes.tosequence(temp.list,nil)) end for i=1,nc do local ci = cache[i] free_nodelist(ci.original) end cache = { } - tex.hbadness = tex_hbadness - tex.hfuzz = tex_hfuzz + tex.hbadness, tex.hfuzz = tex_hbadness, tex_hfuzz stoptiming(splitters) end diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua index 6296f088e..5b50ac75f 100644 --- a/tex/context/base/font-syn.lua +++ b/tex/context/base/font-syn.lua @@ -81,33 +81,7 @@ directives.register("fonts.usesystemfonts", function(v) usesystemfonts = toboole local P, C, Cc, Cs = lpeg.P, lpeg.C, lpeg.Cc, lpeg.Cs --- -- what to do with these -- -- --- --- thin -> thin --- --- regu -> regular -> normal --- norm -> normal -> normal --- stan -> standard -> normal --- medi -> medium --- ultr -> ultra --- ligh -> light --- heav -> heavy --- blac -> black --- thin --- book --- verylight --- --- buch -> book --- buchschrift -> book --- halb -> demi --- halbfett -> demi --- mitt -> medium --- mittel -> medium --- fett -> bold --- mage -> light --- mager -> light --- nord -> normal --- gras -> normal +-- what to do with 'thin' local weights = Cs ( -- not extra P("demibold") @@ -116,7 +90,6 @@ local weights = Cs ( -- not extra + P("ultrabold") + P("extrabold") + P("ultralight") - + P("extralight") + P("bold") + P("demi") + P("semi") @@ -130,17 +103,6 @@ local weights = Cs ( -- not extra + P("regular") / "normal" ) --- numeric_weights = { --- 200 = "extralight", --- 300 = "light", --- 400 = "book", --- 500 = "medium", --- 600 = "demi", --- 700 = "bold", --- 800 = "heavy", --- 900 = "black", --- } - local normalized_weights = sparse { regular = "normal", } @@ -154,7 +116,6 @@ local styles = Cs ( + P("roman") / "normal" + P("ital") / "italic" -- might be tricky + P("ita") / "italic" -- might be tricky ---+ P("obli") / "oblique" ) local normalized_styles = sparse { @@ -168,7 +129,6 @@ local widths = Cs( + P("thin") + P("expanded") + P("cond") / "condensed" ---+ P("expa") / "expanded" + P("normal") + P("book") / "normal" ) @@ -308,9 +268,6 @@ filters.dfont = fontloader.info -- glyphs so here we first load and then discard which is a waste. In the past it did -- free memory because a full load was done. One of these things that goes unnoticed. -- --- missing: names, units_per_em, design_range_bottom, design_range_top, design_size, --- pfminfo, top_side_bearing - -- function fontloader.fullinfo(...) -- check with taco what we get / could get -- local ff = fontloader.open(...) -- if ff then @@ -326,7 +283,7 @@ filters.dfont = fontloader.info -- Phillip suggested this faster variant but it's still a hack as fontloader.info should -- return these keys/values (and maybe some more) but at least we close the loader which -- might save some memory in the end. - +-- -- function fontloader.fullinfo(name) -- local ff = fontloader.open(name) -- if ff then @@ -344,9 +301,8 @@ filters.dfont = fontloader.info -- design_size = fields.design_size and ff.design_size, -- italicangle = fields.italicangle and ff.italicangle, -- pfminfo = fields.pfminfo and ff.pfminfo, --- top_side_bearing = fields.top_side_bearing and ff.top_side_bearing, -- } --- setmetatableindex(d,function(t,k) +-- table.setmetatableindex(d,function(t,k) -- report_names("warning, trying to access field %a in font table of %a",k,name) -- end) -- fontloader.close(ff) @@ -357,26 +313,19 @@ filters.dfont = fontloader.info -- end -- As we have lazy loading anyway, this one still is full and with less code than --- the previous one. But this depends on the garbage collector to kick in. +-- the previous one. function fontloader.fullinfo(...) local ff = fontloader.open(...) if ff then local d = { } -- ff is userdata so [1] or # fails on it - setmetatableindex(d,ff) + table.setmetatableindex(d,ff) return d else return nil, "error in loading font" end end --- We don't get the design_* values here as for that the fontloader has to load feature --- info and therefore we're not much better off than using 'open'. --- --- if tonumber(status.luatex_version) > 78 or (tonumber(status.luatex_version) == 78 and tonumber(status.luatex_revision) > 0) then --- fontloader.fullinfo = fontloader.info --- end - filters.otf = fontloader.fullinfo filters.ttf = fontloader.fullinfo @@ -598,7 +547,7 @@ local function check_name(data,result,filename,modification,suffix,subfont) fullname = fullname or fontname familyname = familyname or fontname -- we do these sparse - local units = result.units_per_em or 1000 -- can be zero too + local units = result.units_per_em or 1000 local minsize = result.design_range_bottom or 0 local maxsize = result.design_range_top or 0 local designsize = result.design_size or 0 @@ -622,7 +571,7 @@ local function check_name(data,result,filename,modification,suffix,subfont) style = style, width = width, variant = variant, - units = units ~= 1000 and units or nil, + units = units ~= 1000 and unit or nil, pfmwidth = pfmwidth ~= 0 and pfmwidth or nil, pfmweight = pfmweight ~= 0 and pfmweight or nil, angle = angle ~= 0 and angle or nil, @@ -631,9 +580,6 @@ local function check_name(data,result,filename,modification,suffix,subfont) designsize = designsize ~= 0 and designsize or nil, modification = modification ~= 0 and modification or nil, } --- inspect(filename) --- inspect(result) --- inspect(specifications[#specifications]) end local function cleanupkeywords() diff --git a/tex/context/base/l-dir.lua b/tex/context/base/l-dir.lua index b658b7c75..40081cc3b 100644 --- a/tex/context/base/l-dir.lua +++ b/tex/context/base/l-dir.lua @@ -25,7 +25,6 @@ local isdir = lfs.isdir local isfile = lfs.isfile local currentdir = lfs.currentdir local chdir = lfs.chdir -local mkdir = lfs.mkdir local onwindows = os.type == "windows" or find(os.getenv("PATH"),";") @@ -285,28 +284,17 @@ local make_indeed = true -- false if onwindows then function dir.mkdirs(...) - local n = select("#",...) - local str - if n == 1 then - str = select(1,...) - if isdir(str) then - return str, true - end - else - str = "" - for i=1,n do - local s = select(i,...) - local s = select(i,...) - if s == "" then - -- skip - elseif str == "" then - str = s - else - str = str .. "/" .. s - end + local str, pth = "", "" + for i=1,select("#",...) do + local s = select(i,...) + if s == "" then + -- skip + elseif str == "" then + str = s + else + str = str .. "/" .. s end end - local pth = "" local drive = false local first, middle, last = match(str,"^(//)(//*)(.*)$") if first then @@ -342,7 +330,7 @@ if onwindows then pth = pth .. "/" .. s end if make_indeed and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end return pth, (isdir(pth) == true) @@ -363,23 +351,14 @@ if onwindows then else function dir.mkdirs(...) - local n = select("#",...) - local str, pth - if n == 1 then - str = select(1,...) - if isdir(str) then - return str, true - end - else - str = "" - for i=1,n do - local s = select(i,...) - if s and s ~= "" then -- we catch nil and false - if str ~= "" then - str = str .. "/" .. s - else - str = s - end + local str, pth = "", "" + for i=1,select("#",...) do + local s = select(i,...) + if s and s ~= "" then -- we catch nil and false + if str ~= "" then + str = str .. "/" .. s + else + str = s end end end @@ -394,7 +373,7 @@ else pth = pth .. "/" .. s end if make_indeed and not first and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end else @@ -402,7 +381,7 @@ else for s in gmatch(str,"[^/]+") do pth = pth .. "/" .. s if make_indeed and not isdir(pth) then - mkdir(pth) + lfs.mkdir(pth) end end end diff --git a/tex/context/base/l-lpeg.lua b/tex/context/base/l-lpeg.lua index 6feb7089c..399b3ad65 100644 --- a/tex/context/base/l-lpeg.lua +++ b/tex/context/base/l-lpeg.lua @@ -6,10 +6,6 @@ if not modules then modules = { } end modules ['l-lpeg'] = { license = "see context related readme files" } --- lpeg 12 vs lpeg 10: slower compilation, similar parsing speed (i need to check --- if i can use new features like capture / 2 and .B (at first sight the xml --- parser is some 5% slower) - -- a new lpeg fails on a #(1-P(":")) test and really needs a + P(-1) -- move utf -> l-unicode @@ -19,15 +15,14 @@ lpeg = require("lpeg") -- The latest lpeg doesn't have print any more, and even the new ones are not -- available by default (only when debug mode is enabled), which is a pitty as --- as it helps nailign down bottlenecks. Performance seems comparable: some 10% --- slower pattern compilation, same parsing speed, although, +-- as it helps bailign down bottlenecks. Performance seems comparable, although -- -- local p = lpeg.C(lpeg.P(1)^0 * lpeg.P(-1)) --- local a = string.rep("123",100) +-- local a = string.rep("123",10) -- lpeg.match(p,a) -- --- seems slower and is also still suboptimal (i.e. a match that runs from begin --- to end, one of the cases where string matchers win). +-- is nearly 20% slower and also still suboptimal (i.e. a match that runs from +-- begin to end, one of the cases where string matchers win). if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end @@ -79,9 +74,7 @@ local lpegtype, lpegmatch, lpegprint = lpeg.type, lpeg.match, lpeg.print -- let's start with an inspector: -if setinspector then - setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) -end +setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) -- Beware, we predefine a bunch of patterns here and one reason for doing so -- is that we get consistent behaviour in some of the visualizers. @@ -176,14 +169,12 @@ patterns.whitespace = whitespace patterns.nonspacer = nonspacer patterns.nonwhitespace = nonwhitespace -local stripper = spacer ^0 * C((spacer ^0 * nonspacer ^1)^0) -- from example by roberto -local fullstripper = whitespace^0 * C((whitespace^0 * nonwhitespace^1)^0) +local stripper = spacer^0 * C((spacer^0 * nonspacer^1)^0) -- from example by roberto ----- collapser = Cs(spacer^0/"" * ((spacer^1 * endofstring / "") + (spacer^1/" ") + P(1))^0) local collapser = Cs(spacer^0/"" * nonspacer^0 * ((spacer^0/" " * nonspacer^1)^0)) patterns.stripper = stripper -patterns.fullstripper = fullstripper patterns.collapser = collapser patterns.lowercase = lowercase @@ -478,7 +469,7 @@ end -- local pattern1 = P(1-P(pattern))^0 * P(pattern) : test for not nil -- local pattern2 = (P(pattern) * Cc(true) + P(1))^0 : test for true (could be faster, but not much) -function lpeg.finder(lst,makefunction,isutf) -- beware: slower than find with 'patternless finds' +function lpeg.finder(lst,makefunction) -- beware: slower than find with 'patternless finds' local pattern if type(lst) == "table" then pattern = P(false) @@ -494,12 +485,7 @@ function lpeg.finder(lst,makefunction,isutf) -- beware: slower than find with 'p else pattern = P(lst) end - if isutf then --- pattern = ((utf8char or 1)-pattern)^0 * pattern - pattern = ((utf8char or 1)-pattern)^0 * pattern - else - pattern = (1-pattern)^0 * pattern - end + pattern = (1-pattern)^0 * pattern if makefunction then return function(str) return lpegmatch(pattern,str) diff --git a/tex/context/base/l-lua.lua b/tex/context/base/l-lua.lua index 4a96b0b1d..fc05afa67 100644 --- a/tex/context/base/l-lua.lua +++ b/tex/context/base/l-lua.lua @@ -148,9 +148,3 @@ function optionalrequire(...) return result end end - --- nice for non ascii scripts (this might move): - -if lua then - lua.mask = load([[τεχ = 1]]) and "utf" or "ascii" -end diff --git a/tex/context/base/l-string.lua b/tex/context/base/l-string.lua index 3b1a0003f..9b079b00a 100644 --- a/tex/context/base/l-string.lua +++ b/tex/context/base/l-string.lua @@ -70,7 +70,6 @@ function string.limit(str,n,sentinel) -- not utf proof end local stripper = patterns.stripper -local fullstripper = patterns.fullstripper local collapser = patterns.collapser local longtostring = patterns.longtostring @@ -78,10 +77,6 @@ function string.strip(str) return lpegmatch(stripper,str) or "" end -function string.fullstrip(str) - return lpegmatch(fullstripper,str) or "" -end - function string.collapsespaces(str) return lpegmatch(collapser,str) or "" end diff --git a/tex/context/base/l-table.lua b/tex/context/base/l-table.lua index c318c57bb..f361f3d20 100644 --- a/tex/context/base/l-table.lua +++ b/tex/context/base/l-table.lua @@ -1006,9 +1006,7 @@ function table.print(t,...) end end -if setinspector then - setinspector(function(v) if type(v) == "table" then serialize(print,v,"table") return true end end) -end +setinspector(function(v) if type(v) == "table" then serialize(print,v,"table") return true end end) -- -- -- obsolete but we keep them for a while and might comment them later -- -- -- diff --git a/tex/context/base/l-url.lua b/tex/context/base/l-url.lua index 7bb731254..7b7910fa7 100644 --- a/tex/context/base/l-url.lua +++ b/tex/context/base/l-url.lua @@ -26,8 +26,6 @@ local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replac -- | ___________|____________ | -- / \ / \ | -- urn:example:animal:ferret:nose interpretable as extension --- --- also nice: http://url.spec.whatwg.org/ (maybe some day ...) url = url or { } local url = url @@ -45,7 +43,7 @@ local hexdigit = R("09","AF","af") local plus = P("+") local nothing = Cc("") local escapedchar = (percent * C(hexdigit * hexdigit)) / tochar -local escaped = (plus / " ") + escapedchar -- so no loc://foo++.tex +local escaped = (plus / " ") + escapedchar local noslash = P("/") / "" @@ -191,11 +189,7 @@ local function hashed(str) -- not yet ok (/test?test) return s end --- inspect(hashed("template:///test")) --- inspect(hashed("template:///test++.whatever")) --- inspect(hashed("template:///test%2B%2B.whatever")) --- inspect(hashed("template:///test%x.whatever")) --- inspect(hashed("tem%2Bplate:///test%x.whatever")) +-- inspect(hashed("template://test")) -- Here we assume: -- diff --git a/tex/context/base/lang-lab.mkiv b/tex/context/base/lang-lab.mkiv index 14d9d8594..1ddb44cbb 100644 --- a/tex/context/base/lang-lab.mkiv +++ b/tex/context/base/lang-lab.mkiv @@ -94,10 +94,8 @@ \csname\??label\currentlabelcategory#1:##1:##2\endcsname \else\ifcsname\??label#1:##1:##2\endcsname \csname\??label#1:##1:##2\endcsname -% \else\ifcsname\??language#4\s!default\endcsname -% \expandafter#5\csname\??language#4\s!default\endcsname{##2}% - \else\ifcsname\??language##1\s!default\endcsname - \expandafter#5\csname\??language##1\s!default\endcsname{##2}% + \else\ifcsname\??language#4\s!default\endcsname + \expandafter#5\csname\??language#4\s!default\endcsname{##2}% \else\ifcsname\??label\currentlabelcategory#1:##2\endcsname \csname\??label\currentlabelcategory#1:##2\endcsname \else\ifcsname\??label#1:##2\endcsname diff --git a/tex/context/base/lang-rep.lua b/tex/context/base/lang-rep.lua index be74d597a..31ae36e6d 100644 --- a/tex/context/base/lang-rep.lua +++ b/tex/context/base/lang-rep.lua @@ -7,21 +7,9 @@ if not modules then modules = { } end modules ['lang-rep'] = { } -- A BachoTeX 2013 experiment, probably not that useful. Eventually I used a simpler --- more generic example. I'm sure no one ever notices of even needs this code. --- --- As a follow up on a question by Alan about special treatment of dropped caps I wonder --- if I can make this one more clever (probably in a few more dev steps). For instance --- injecting nodes or replacing nodes. It's a prelude to a kind of lpeg for nodes, --- although (given experiences so far) we don't really need that. After all, each problem --- is somewhat unique. +-- more generic example. -local type = type local utfbyte, utfsplit = utf.byte, utf.split -local P, C, U, Cc, Ct, lpegmatch = lpeg.P, lpeg.C, lpeg.patterns.utf8character, lpeg.Cc, lpeg.Ct, lpeg.match -local find = string.find - -local grouped = P("{") * ( Ct((U/utfbyte-P("}"))^1) + Cc(false) ) * P("}")-- grouped -local splitter = Ct((Ct(Cc("discretionary") * grouped * grouped * grouped) + U/utfbyte)^1) local trace_replacements = false trackers.register("languages.replacements", function(v) trace_replacements = v end) local trace_detail = false trackers.register("languages.replacements.detail", function(v) trace_detail = v end) @@ -30,26 +18,9 @@ local report_replacement = logs.reporter("languages","replacements") local glyph_code = nodes.nodecodes.glyph -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getattr = nuts.getattr -local getid = nuts.getid -local getchar = nuts.getchar - -local insert_node_before = nuts.insert_before -local remove_node = nuts.remove -local copy_node = nuts.copy -local flush_list = nuts.flush_list -local insert_after = nuts.insert_after - -local nodepool = nuts.pool -local new_glyph = nodepool.glyph -local new_disc = nodepool.disc +local insert_node_before = nodes.insert_before +local remove_node = nodes.remove +local copy_node = nodes.copy local texsetattribute = tex.setattribute local unsetvalue = attributes.unsetvalue @@ -75,30 +46,23 @@ table.setmetatableindex(lists,function(lists,name) return data end) --- todo: glue kern - local function add(root,word,replacement) local list = utfsplit(word,true) - local size = #list - for i=1,size do + for i=1,#list do local l = utfbyte(list[i]) if not root[l] then root[l] = { } end - if i == size then - -- local newlist = utfsplit(replacement,true) - -- for i=1,#newlist do - -- newlist[i] = utfbyte(newlist[i]) - -- end - local special = find(replacement,"{") - local newlist = lpegmatch(splitter,replacement) - -- + if i == #list then + local newlist = utfsplit(replacement,true) + for i=1,#newlist do + newlist[i] = utfbyte(newlist[i]) + end root[l].final = { word = word, replacement = replacement, - oldlength = size, + oldlength = #list, newcodes = newlist, - special = special, } end root = root[l] @@ -119,13 +83,13 @@ end local function hit(a,head) local tree = trees[a] if tree then - local root = tree[getchar(head)] + local root = tree[head.char] if root then - local current = getnext(head) + local current = head.next local lastrun = false local lastfinal = false - while current and getid(current) == glyph_code do - local newroot = root[getchar(current)] + while current and current.id == glyph_code do + local newroot = root[current.char] if not newroot then return lastrun, lastfinal else @@ -140,7 +104,7 @@ local function hit(a,head) root = newroot end end - current = getnext(current) + current = current.next end if lastrun then return lastrun, lastfinal @@ -149,27 +113,11 @@ local function hit(a,head) end end -local function tonodes(list,template) - local head, current - for i=1,#list do - local new = copy_node(template) - setfield(new,"char",list[i]) - if head then - head, current = insert_after(head,current,new) - else - head, current = new, new - end - end - return head -end - - function replacements.handler(head) - head = tonut(head) local current = head local done = false while current do - if getid(current) == glyph_code then + if current.id == glyph_code then local a = getattr(current,a_replacements) if a then local last, final = hit(a,current) @@ -177,85 +125,41 @@ function replacements.handler(head) local oldlength = final.oldlength local newcodes = final.newcodes local newlength = #newcodes - if trace_replacement then + if report_replacement then report_replacement("replacing word %a by %a",final.word,final.replacement) end - if final.special then - -- easier is to delete and insert (a simple callout to tex would be more efficient) - -- maybe just walk over a replacement string instead - local prev = getprev(current) - local next = getnext(last) - local list = current - setfield(last,"next",nil) - setfield(prev,"next",next) - if next then - setfield(next,"prev",prev) - end - current = prev - if not current then - head = nil - end - for i=1,newlength do - local codes = newcodes[i] - local new = nil - if type(codes) == "table" then - local method = codes[1] - if method == "discretionary" then - local pre, post, replace = codes[2], codes[3], codes[4] - new = new_disc() - if pre then - setfield(new,"pre",tonodes(pre,last)) - end - if post then - setfield(new,"post",tonodes(post,last)) - end - if replace then - setfield(new,"replace",tonodes(replace,last)) - end - else - -- todo - end - else - new = copy_node(last) - setfield(new,"char",codes) - end - if new then - head, current = insert_after(head,current,new) - end - end - flush_list(list) - elseif oldlength == newlength then -- #old == #new + if oldlength == newlength then -- #old == #new for i=1,newlength do - setfield(current,"char",newcodes[i]) - current = getnext(current) + current.char = newcodes[i] + current = current.next end elseif oldlength < newlength then -- #old < #new for i=1,newlength-oldlength do local n = copy_node(current) - setfield(n,"char",newcodes[i]) + n.char = newcodes[i] head, current = insert_node_before(head,current,n) - current = getnext(current) + current = current.next end for i=newlength-oldlength+1,newlength do - setfield(current,"char",newcodes[i]) - current = getnext(current) + current.char = newcodes[i] + current = current.next end else -- #old > #new for i=1,oldlength-newlength do head, current = remove_node(head,current,true) end for i=1,newlength do - setfield(current,"char",newcodes[i]) - current = getnext(current) + current.char = newcodes[i] + current = current.next end end done = true end end end - current = getnext(current) + current = current.next end - return tonode(head), done + return head, done end local enabled = false @@ -280,3 +184,6 @@ end commands.setreplacements = replacements.set commands.addreplacements = replacements.add + +nodes.tasks.prependaction("processors","words","languages.replacements.handler") +nodes.tasks.disableaction("processors","languages.replacements.handler") diff --git a/tex/context/base/lang-rep.mkiv b/tex/context/base/lang-rep.mkiv deleted file mode 100644 index b3f21f22a..000000000 --- a/tex/context/base/lang-rep.mkiv +++ /dev/null @@ -1,75 +0,0 @@ -%D \module -%D [ file=lang-rep, -%D version=2013.04.28, -%D title=\CONTEXT\ Language Macros, -%D subtitle=Substitution, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D As I needed an example of messing with nodes for the bacho\TEX\ tutorial -%D I cooked up this. In the end I decided to stick to a simpler example and -%D just finished this off in case someone really needs it. - -\writestatus{loading}{ConTeXt Language Macros / Replacements} - -\unprotect - -\registerctxluafile{lang-rep}{1.001} - -\definesystemattribute[replacements][public] - -%D \startluacode -%D -%D -- todo: other nodes (prelude to more experiments with auto dropped caps) -%D -%D languages.replacements.add("basics", { -%D ["aap"] = "monkey", -%D ["noot"] = "nut", -%D ["never"] = "forever", -%D ["newer"] = "cooler", -%D ["new"] = "cool", -%D -- ["special"] = "veryspe{>>>}{<<<}{=}cial", -%D }) -%D -%D \stopluacode -%D -%D \replaceword[more][this][that] -%D \replaceword[more][crap][support] -%D \replaceword[more][---][—] -%D \replaceword[basics][special][veryspe{>>>}{<<<}{=}cial] -%D -%D \starttyping -%D \start \setreplacements[basics] What the heck, it's now or never, isn't it new? \par \stop -%D \start \setreplacements[more] Do we --- {\it really} --- need this kind of crap? \par \stop -%D \start \setreplacements[basics] All kinds of special thingies! \par \stop -%D \start \setreplacements[basics] \hsize1mm special \par \stop -%D \stoptyping - -\unexpanded\def\setreplacements[#1]% - {\ctxcommand{setreplacements("#1")}} - -\unexpanded\def\resetreplacements - {\attribute\replacementsattribute\attributeunsetvalue} - -\unexpanded\def\replaceword - {\dotripleargument\languages_replacements_replace} - -\unexpanded\def\languages_replacements_replace[#1][#2][#3]% - {\ifthirdargument - \ctxcommand{addreplacements("#1",\!!bs#2\!!es,\!!bs#3\!!es)}% - \fi} - -\appendtoks - \resetreplacements -\to \everyresettypesetting - -\appendtoks - \resetreplacements -\to \everyinitializeverbatim - -\protect \endinput diff --git a/tex/context/base/lang-wrd.lua b/tex/context/base/lang-wrd.lua index 5fc23757e..bf066fc09 100644 --- a/tex/context/base/lang-wrd.lua +++ b/tex/context/base/lang-wrd.lua @@ -26,18 +26,7 @@ words.threshold = 4 local numbers = languages.numbers local registered = languages.registered -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local setattr = nuts.setattr - -local traverse_nodes = nuts.traverse - +local traverse_nodes = node.traverse local wordsdata = words.data local chardata = characters.data local tasks = nodes.tasks @@ -107,7 +96,7 @@ end -- there is an n=1 problem somewhere in nested boxes local function mark_words(head,whenfound) -- can be optimized and shared - local current, language, done = tonut(head), nil, nil, 0, false + local current, language, done = head, nil, nil, 0, false local str, s, nds, n = { }, 0, { }, 0 -- n could also be a table, saves calls local function action() if s > 0 then @@ -123,9 +112,9 @@ local function mark_words(head,whenfound) -- can be optimized and shared n, s = 0, 0 end while current do - local id = getid(current) + local id = current.id if id == glyph_code then - local a = getfield(current,"lang") + local a = current.lang if a then if a ~= language then if s > 0 then @@ -137,16 +126,16 @@ local function mark_words(head,whenfound) -- can be optimized and shared action() language = a end - local components = getfield(current,"components") + local components = current.components if components then n = n + 1 nds[n] = current for g in traverse_nodes(components) do s = s + 1 - str[s] = utfchar(getchar(g)) + str[s] = utfchar(g.char) end else - local code = getchar(current) + local code = current.char local data = chardata[code] if is_letter[data.category] then n = n + 1 @@ -162,12 +151,12 @@ local function mark_words(head,whenfound) -- can be optimized and shared n = n + 1 nds[n] = current end - elseif id == kern_code and getsubtype(current) == kerning_code and s > 0 then + elseif id == kern_code and current.subtype == kerning_code and s > 0 then -- ok elseif s > 0 then action() end - current = getnext(current) + current = current.next end if s > 0 then action() @@ -187,8 +176,6 @@ local enabled = false function words.check(head) if enabled then return methods[wordmethod](head) - elseif not head then - return head, false else return head, false end @@ -220,7 +207,7 @@ table.setmetatableindex(cache, function(t,k) -- k == language, numbers[k] == tag else c = colist["word:" .. (numbers[k] or "unset")] or colist["word:unknown"] end - local v = c and function(n) setattr(n,a_color,c) end or false + local v = c and function(n) n[a_color] = c end or false t[k] = v return v end) @@ -239,7 +226,7 @@ end methods[1] = function(head) for n in traverse_nodes(head) do - setattr(n,a_color,unsetvalue) -- hm, not that selective (reset color) + n[a_color] = unsetvalue -- hm, not that selective (reset color) end return mark_words(head,sweep) end @@ -340,7 +327,7 @@ end methods[3] = function(head) for n in traverse_nodes(head) do - setattr(n,a_color,unsetvalue) + n[a_color] = unsetvalue end return mark_words(head,sweep) end diff --git a/tex/context/base/lpdf-mis.lua b/tex/context/base/lpdf-mis.lua index 43f6cb7e1..174d17427 100644 --- a/tex/context/base/lpdf-mis.lua +++ b/tex/context/base/lpdf-mis.lua @@ -43,7 +43,6 @@ local pdfflushobject = lpdf.flushobject local pdfflushstreamobject = lpdf.flushstreamobject local variables = interfaces.variables -local v_stop = variables.stop local positive = register(pdfliteral("/GSpositive gs")) local negative = register(pdfliteral("/GSnegative gs")) @@ -338,82 +337,31 @@ local map = { characters = "a", } --- local function featurecreep() --- local pages, lastconversion, list = structures.pages.tobesaved, nil, pdfarray() --- local getstructureset = structures.sets.get --- for i=1,#pages do --- local p = pages[i] --- if not p then --- return -- fatal error --- else --- local numberdata = p.numberdata --- if numberdata then --- local conversionset = numberdata.conversionset --- if conversionset then --- local conversion = getstructureset("structure:conversions",p.block,conversionset,1,"numbers") --- if conversion ~= lastconversion then --- lastconversion = conversion --- list[#list+1] = i - 1 -- pdf starts numbering at 0 --- list[#list+1] = pdfdictionary { S = pdfconstant(map[conversion] or map.numbers) } --- end --- end --- end --- if not lastconversion then --- lastconversion = "numbers" --- list[#list+1] = i - 1 -- pdf starts numbering at 0 --- list[#list+1] = pdfdictionary { S = pdfconstant(map.numbers) } --- end --- end --- end --- lpdf.addtocatalog("PageLabels", pdfdictionary { Nums = list }) --- end - local function featurecreep() - local pages = structures.pages.tobesaved - local list = pdfarray() - local getset = structures.sets.get - local stopped = false - local oldlabel = nil - local olconversion = nil + local pages, lastconversion, list = structures.pages.tobesaved, nil, pdfarray() + local getstructureset = structures.sets.get for i=1,#pages do local p = pages[i] if not p then return -- fatal error - end - local label = p.viewerprefix or "" - if p.status == v_stop then - if not stopped then - list[#list+1] = i - 1 -- pdf starts numbering at 0 - list[#list+1] = pdfdictionary { - P = pdfunicode(label), - } - stopped = true - end - oldlabel = nil - oldconversion = nil - stopped = false else local numberdata = p.numberdata - local conversion = nil - local number = p.number if numberdata then local conversionset = numberdata.conversionset if conversionset then - conversion = getset("structure:conversions",p.block,conversionset,1,"numbers") + local conversion = getstructureset("structure:conversions",p.block,conversionset,1,"numbers") + if conversion ~= lastconversion then + lastconversion = conversion + list[#list+1] = i - 1 -- pdf starts numbering at 0 + list[#list+1] = pdfdictionary { S = pdfconstant(map[conversion] or map.numbers) } + end end end - conversion = conversion and map[conversion] or map.numbers - if number == 1 or oldlabel ~= label or oldconversion ~= conversion then + if not lastconversion then + lastconversion = "numbers" list[#list+1] = i - 1 -- pdf starts numbering at 0 - list[#list+1] = pdfdictionary { - S = pdfconstant(conversion), - St = number, - P = label ~= "" and pdfunicode(label) or nil, - } + list[#list+1] = pdfdictionary { S = pdfconstant(map.numbers) } end - oldlabel = label - oldconversion = conversion - stopped = false end end lpdf.addtocatalog("PageLabels", pdfdictionary { Nums = list }) diff --git a/tex/context/base/lpdf-nod.lua b/tex/context/base/lpdf-nod.lua index 68d7fca90..6b104d2fa 100644 --- a/tex/context/base/lpdf-nod.lua +++ b/tex/context/base/lpdf-nod.lua @@ -6,29 +6,21 @@ if not modules then modules = { } end modules ['lpdf-nod'] = { license = "see context related readme files" } -local type = type - local formatters = string.formatters -local whatsitcodes = nodes.whatsitcodes -local nodeinjections = backends.nodeinjections - -local nuts = nodes.nuts -local tonut = nuts.tonut - -local setfield = nuts.setfield - -local copy_node = nuts.copy -local new_node = nuts.new +local copy_node = node.copy +local new_node = node.new -local nodepool = nuts.pool +local nodepool = nodes.pool local register = nodepool.register +local whatsitcodes = nodes.whatsitcodes +local nodeinjections = backends.nodeinjections -local pdfliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) setfield(pdfliteral,"mode",1) +local pdfliteral = register(new_node("whatsit", whatsitcodes.pdfliteral)) pdfliteral.mode = 1 local pdfsave = register(new_node("whatsit", whatsitcodes.pdfsave)) local pdfrestore = register(new_node("whatsit", whatsitcodes.pdfrestore)) local pdfsetmatrix = register(new_node("whatsit", whatsitcodes.pdfsetmatrix)) -local pdfdest = register(new_node("whatsit", whatsitcodes.pdfdest)) setfield(pdfdest,"named_id",1) -- xyz_zoom untouched +local pdfdest = register(new_node("whatsit", whatsitcodes.pdfdest)) pdfdest.named_id = 1 -- xyz_zoom untouched local pdfannot = register(new_node("whatsit", whatsitcodes.pdfannot)) local variables = interfaces.variables @@ -46,14 +38,14 @@ local views = { -- beware, we do support the pdf keys but this is *not* official function nodepool.pdfliteral(str) local t = copy_node(pdfliteral) - setfield(t,"data",str) + t.data = str return t end function nodepool.pdfdirect(str) local t = copy_node(pdfliteral) - setfield(t,"data",str) - setfield(t,"mode",1) + t.data = str + t.mode = 1 return t end @@ -65,10 +57,16 @@ function nodepool.pdfrestore() return copy_node(pdfrestore) end -function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty) -- todo: tx ty +function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty) + local t = copy_node(pdfsetmatrix) + t.data = formatters["%s %s %s %s"](rx or 0,sx or 0,sy or 0,ry or 0) -- todo: tx ty + return t +end + +function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty) local t = copy_node(pdfsetmatrix) if type(rx) == "string" then - setfield(t,"data",rx) + t.data = rx else if not rx then rx = 1 @@ -88,12 +86,12 @@ function nodepool.pdfsetmatrix(rx,sx,sy,ry,tx,ty) -- todo: tx ty end if sx == 0 and sy == 0 then if rx == 1 and ry == 1 then - setfield(t,"data","1 0 0 1") + t.data = "1 0 0 1" else - setfield(t,"data",formatters["%0.6f 0 0 %0.6f"](rx,ry)) + t.data = formatters["%0.6f 0 0 %0.6f"](rx,ry) end else - setfield(t,"data",formatters["%0.6f %0.6f %0.6f %0.6f"](rx,sx,sy,ry)) + t.data = formatters["%0.6f %0.6f %0.6f %0.6f"](rx,sx,sy,ry) end end return t @@ -106,19 +104,19 @@ nodeinjections.transform = nodepool.pdfsetmatrix function nodepool.pdfannotation(w,h,d,data,n) local t = copy_node(pdfannot) if w and w ~= 0 then - setfield(t,"width",w) + t.width = w end if h and h ~= 0 then - setfield(t,"height",h) + t.height = h end if d and d ~= 0 then - setfield(t,"depth",d) + t.depth = d end if n then - setfield(t,"objnum",n) + t.objnum = n end if data and data ~= "" then - setfield(t,"data",data) + t.data = data end return t end @@ -140,36 +138,35 @@ function nodepool.pdfdestination(w,h,d,name,view,n) local t = copy_node(pdfdest) local hasdimensions = false if w and w ~= 0 then - setfield(t,"width",w) + t.width = w hasdimensions = true end if h and h ~= 0 then - setfield(t,"height",h) + t.height = h hasdimensions = true end if d and d ~= 0 then - setfield(t,"depth",d) + t.depth = d hasdimensions = true end if n then - setfield(t,"objnum",n) + t.objnum = n end view = views[view] or view or 1 -- fit is default - setfield(t,"dest_id",name) - setfield(t,"dest_type",view) + t.dest_id = name + t.dest_type = view if hasdimensions and view == 0 then -- xyz -- see (!) s -> m -> t -> r - -- linked local s = copy_node(pdfsave) local m = copy_node(pdfsetmatrix) local r = copy_node(pdfrestore) - setfield(m,"data","1 0 0 1") - setfield(s,"next",m) - setfield(m,"next",t) - setfield(t,"next",r) - setfield(m,"prev",s) - setfield(t,"prev",m) - setfield(r,"prev",t) + m.data = "1 0 0 1" + s.next = m + m.next = t + t.next = r + m.prev = s + t.prev = m + r.prev = t return s -- a list else return t diff --git a/tex/context/base/lpdf-tag.lua b/tex/context/base/lpdf-tag.lua index afddec345..29ffcd207 100644 --- a/tex/context/base/lpdf-tag.lua +++ b/tex/context/base/lpdf-tag.lua @@ -6,7 +6,6 @@ if not modules then modules = { } end modules ['lpdf-tag'] = { license = "see context related readme files" } -local next = next local format, match, concat = string.format, string.match, table.concat local lpegmatch = lpeg.match local utfchar = utf.char @@ -15,9 +14,7 @@ local trace_tags = false trackers.register("structures.tags", function(v) trace local report_tags = logs.reporter("backend","tags") -local backends = backends -local lpdf = lpdf -local nodes = nodes +local backends, lpdf, nodes = backends, lpdf, nodes local nodeinjections = backends.pdf.nodeinjections local codeinjections = backends.pdf.codeinjections @@ -37,6 +34,10 @@ local pdfpagereference = lpdf.pagereference local texgetcount = tex.getcount +local nodepool = nodes.pool + +local pdfliteral = nodepool.pdfliteral + local nodecodes = nodes.nodecodes local hlist_code = nodecodes.hlist @@ -46,26 +47,11 @@ local glyph_code = nodecodes.glyph local a_tagged = attributes.private('tagged') local a_image = attributes.private('image') -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local nodepool = nuts.pool -local pdfliteral = nodepool.pdfliteral - -local getid = nuts.getid -local getattr = nuts.getattr -local getprev = nuts.getprev -local getnext = nuts.getnext -local getlist = nuts.getlist -local setfield = nuts.setfield - -local traverse_nodes = nuts.traverse -local tosequence = nuts.tosequence -local copy_node = nuts.copy -local slide_nodelist = nuts.slide -local insert_before = nuts.insert_before -local insert_after = nuts.insert_after +local traverse_nodes = node.traverse +local traverse_id = node.traverse_id +local tosequence = nodes.tosequence +local copy_node = node.copy +local slide_nodelist = node.slide local structure_stack = { } local structure_kids = pdfarray() @@ -189,8 +175,7 @@ local function makeelement(fulltag,parent) end local function makecontent(parent,start,stop,slist,id) - local tag = parent.tag - local kids = parent.kids + local tag, kids = parent.tag, parent.kids local last = index if id == "image" then local d = pdfdictionary { @@ -213,29 +198,24 @@ local function makecontent(parent,start,stop,slist,id) end -- local bliteral = pdfliteral(format("/%s <</MCID %s>>BDC",tag,last)) - local eliteral = pdfliteral("EMC") - -- use insert instead: - local prev = getprev(start) + local prev = start.prev if prev then - setfield(prev,"next",bliteral) - setfield(bliteral,"prev",prev) + prev.next, bliteral.prev = bliteral, prev end - setfield(start,"prev",bliteral) - setfield(bliteral,"next",start) - -- use insert instead: - local next = getnext(stop) - if next then - setfield(next,"prev",eliteral) - setfield(eliteral,"next",next) + start.prev, bliteral.next = bliteral, start + if slist and slist.list == start then + slist.list = bliteral + elseif not prev then + report_tags("this can't happen: injection in front of nothing") end - setfield(stop,"next",eliteral) - setfield(eliteral,"prev",stop) -- - if slist and getlist(slist) == start then - setfield(slist,"list",bliteral) - elseif not getprev(start) then - report_tags("this can't happen: injection in front of nothing") + local eliteral = pdfliteral("EMC") + local next = stop.next + if next then + next.prev, eliteral.next = eliteral, next end + stop.next, eliteral.prev = eliteral, stop + -- index = index + 1 list[index] = parent.pref return bliteral, eliteral @@ -247,9 +227,9 @@ local level, last, ranges, range = 0, nil, { }, nil local function collectranges(head,list) for n in traverse_nodes(head) do - local id = getid(n) -- 14: image, 8: literal (mp) + local id = n.id -- 14: image, 8: literal (mp) if id == glyph_code then - local at = getattr(n,a_tagged) + local at = n[a_tagged] if not at then range = nil elseif last ~= at then @@ -260,9 +240,9 @@ local function collectranges(head,list) range[4] = n -- stop end elseif id == hlist_code or id == vlist_code then - local at = getattr(n,a_image) + local at = n[a_image] if at then - local at = getattr(n,a_tagged) + local at = n[a_tagged] if not at then range = nil else @@ -270,7 +250,7 @@ local function collectranges(head,list) end last = nil else - local nl = getlist(n) + local nl = n.list slide_nodelist(nl) -- temporary hack till math gets slided (tracker item) collectranges(nl,n) end @@ -282,7 +262,6 @@ function nodeinjections.addtags(head) -- no need to adapt head, as we always operate on lists level, last, ranges, range = 0, nil, { }, nil initializepage() - head = tonut(head) collectranges(head) if trace_tags then for i=1,#ranges do @@ -316,9 +295,8 @@ function nodeinjections.addtags(head) finishpage() -- can be separate feature -- - -- injectspans(tonut(head)) -- does to work yet + -- injectspans(head) -- does to work yet -- - head = tonode(head) return head, true end diff --git a/tex/context/base/luat-cnf.lua b/tex/context/base/luat-cnf.lua index 4ad6cd69d..3672c603e 100644 --- a/tex/context/base/luat-cnf.lua +++ b/tex/context/base/luat-cnf.lua @@ -23,7 +23,7 @@ texconfig.half_error_line = 50 -- 50 -- obsolete texconfig.expand_depth = 10000 -- 10000 texconfig.hash_extra = 100000 -- 0 texconfig.nest_size = 1000 -- 50 -texconfig.max_in_open = 500 -- 15 -- in fact it's limited to 127 +texconfig.max_in_open = 500 -- 15 texconfig.max_print_line = 10000 -- 79 texconfig.max_strings = 500000 -- 15000 texconfig.param_size = 25000 -- 60 diff --git a/tex/context/base/luat-sto.lua b/tex/context/base/luat-sto.lua index 041050fb8..7a11b7f5e 100644 --- a/tex/context/base/luat-sto.lua +++ b/tex/context/base/luat-sto.lua @@ -163,7 +163,6 @@ storage.register("storage/shared", storage.shared, "storage.shared") local mark = storage.mark if string.patterns then mark(string.patterns) end -if string.formatters then mark(string.formatters) end if lpeg.patterns then mark(lpeg.patterns) end if os.env then mark(os.env) end if number.dimenfactors then mark(number.dimenfactors) end diff --git a/tex/context/base/lxml-tab.lua b/tex/context/base/lxml-tab.lua index 8b34a96a3..3e10eb96d 100644 --- a/tex/context/base/lxml-tab.lua +++ b/tex/context/base/lxml-tab.lua @@ -746,11 +746,8 @@ local function _xmlconvert_(data, settings) end if errorstr and errorstr ~= "" then result.error = true - else - errorstr = nil end result.statistics = { - errormessage = errorstr, entities = { decimals = dcache, hexadecimals = hcache, @@ -1019,28 +1016,26 @@ local function verbose_document(e,handlers) end local function serialize(e,handlers,...) - if e then - local initialize = handlers.initialize - local finalize = handlers.finalize - local functions = handlers.functions - if initialize then - local state = initialize(...) - if not state == true then - return state - end - end - local etg = e.tg - if etg then - (functions[etg] or functions["@el@"])(e,handlers) - -- elseif type(e) == "string" then - -- functions["@tx@"](e,handlers) - else - functions["@dc@"](e,handlers) -- dc ? - end - if finalize then - return finalize() + local initialize = handlers.initialize + local finalize = handlers.finalize + local functions = handlers.functions + if initialize then + local state = initialize(...) + if not state == true then + return state end end + local etg = e.tg + if etg then + (functions[etg] or functions["@el@"])(e,handlers) + -- elseif type(e) == "string" then + -- functions["@tx@"](e,handlers) + else + functions["@dc@"](e,handlers) -- dc ? + end + if finalize then + return finalize() + end end local function xserialize(e,handlers) diff --git a/tex/context/base/m-oldbibtex.mkiv b/tex/context/base/m-oldbibtex.mkiv deleted file mode 100644 index 08c23e7cc..000000000 --- a/tex/context/base/m-oldbibtex.mkiv +++ /dev/null @@ -1,16 +0,0 @@ -%D \module -%D [ file=m-oldbibtex, -%D version=2013.12.12, % based on bibl-apa.tex and later xml variant -%D title=Falback on old method, -%D subtitle=Publications, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is therefore copyrighted -%D by \PRAGMA. See mreadme.pdf for details. - -\loadmarkfile{bibl-bib} -\loadmarkfile{bibl-tra} - -\endinput diff --git a/tex/context/base/math-dir.lua b/tex/context/base/math-dir.lua index 525d07831..507a24e41 100644 --- a/tex/context/base/math-dir.lua +++ b/tex/context/base/math-dir.lua @@ -23,19 +23,8 @@ local trace_directions = false trackers.register("typesetters.directions.math local report_directions = logs.reporter("typesetting","math directions") -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getchar = nuts.getchar -local getid = nuts.getid -local getlist = nuts.getlist -local setfield = nuts.setfield -local getattr = nuts.getattr - -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after +local insert_node_before = nodes.insert_before +local insert_node_after = nodes.insert_after local nodecodes = nodes.nodecodes local tasks = nodes.tasks @@ -44,7 +33,7 @@ local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist -local nodepool = nuts.pool +local nodepool = nodes.pool local new_textdir = nodepool.textdir @@ -72,9 +61,9 @@ local function processmath(head) stop = nil end while current do - local id = getid(current) + local id = current.id if id == glyph_code then - local char = getchar(current) + local char = current.char local cdir = chardirections[char] if cdir == "en" or cdir == "an" then -- we could check for mathclass punctuation if not start then @@ -94,7 +83,7 @@ local function processmath(head) if mirror then local class = charclasses[char] if class == "open" or class == "close" then - setfield(current,"char",mirror) + current.char = mirror if trace_directions then report_directions("mirrored: %C to %C",char,mirror) end @@ -105,13 +94,6 @@ local function processmath(head) end elseif not start then -- nothing -if id == hlist_code or id == vlist_code then - local list, d = processmath(getlist(current)) - setfield(current,"list",list) - if d then - done = true - end -end elseif start == stop then start = nil else @@ -119,14 +101,14 @@ end -- math can pack things into hlists .. we need to make sure we don't process -- too often: needs checking if id == hlist_code or id == vlist_code then - local list, d = processmath(getlist(current)) - setfield(current,"list",list) + local list, d = processmath(current.list) + current.list = list if d then done = true end end end - current = getnext(current) + current = current.next end if not start then -- nothing @@ -142,11 +124,9 @@ local enabled = false function directions.processmath(head) -- style, penalties if enabled then - local h = tonut(head) - local a = getattr(h,a_mathbidi) + local a = head[a_mathbidi] if a and a > 0 then - local head, done = processmath(h) - return tonode(head), done + return processmath(head) end end return head, false diff --git a/tex/context/base/math-fbk.lua b/tex/context/base/math-fbk.lua index f4bd1348a..bd9a1d315 100644 --- a/tex/context/base/math-fbk.lua +++ b/tex/context/base/math-fbk.lua @@ -133,8 +133,10 @@ function fallbacks.apply(target,original) else -- something else end - if trace_fallbacks and characters[k] then - report_fallbacks("extending math font %a with %U",target.properties.fullname,k) + if trace_fallbacks then + if characters[k] then + report_fallbacks("extending math font %a with %U",target.properties.fullname,k) + end end end end @@ -332,10 +334,9 @@ end local function accent_to_extensible(target,newchr,original,oldchr,height,depth,swap,offset) local characters = target.characters + local addprivate = fonts.helpers.addprivate local olddata = characters[oldchr] - -- brrr ... pagella has only next - if olddata and not olddata.commands and olddata.width > 0 then - local addprivate = fonts.helpers.addprivate + if olddata and not olddata.commands then if swap then swap = characters[swap] height = swap.depth @@ -398,9 +399,9 @@ local function accent_to_extensible(target,newchr,original,oldchr,height,depth,s end end end - return glyphdata, true + return glyphdata else - return olddata, false + return olddata end end @@ -444,9 +445,9 @@ addextra(0xFE3DF, { description="EXTENSIBLE OF 0x03DF", unicodeslot=0xFE3DF, mat addextra(0xFE3DD, { description="EXTENSIBLE OF 0x03DD", unicodeslot=0xFE3DD, mathextensible = "r", mathstretch = "h" } ) addextra(0xFE3B5, { description="EXTENSIBLE OF 0x03B5", unicodeslot=0xFE3B5, mathextensible = "r", mathstretch = "h" } ) -virtualcharacters[0xFE3DF] = function(data) return data.target.characters[0x23DF] end -virtualcharacters[0xFE3DD] = function(data) return data.target.characters[0x23DD] end -virtualcharacters[0xFE3B5] = function(data) return data.target.characters[0x23B5] end +virtualcharacters[0xFE3DF] = function(data) return data.original.characters[0x23DF] end +virtualcharacters[0xFE3DD] = function(data) return data.original.characters[0x23DD] end +virtualcharacters[0xFE3B5] = function(data) return data.original.characters[0x23B5] end -- todo: add some more .. numbers might change @@ -456,10 +457,8 @@ addextra(0xFE303, { description="EXTENSIBLE OF 0x0303", unicodeslot=0xFE303, mat local function smashed(data,unicode,private) local target = data.target local height = target.parameters.xheight / 2 - local c, done = accent_to_extensible(target,private,data.original,unicode,height,0,nil,-height) - if done then - c.top_accent = nil -- or maybe also all the others - end + local c = accent_to_extensible(target,private,data.original,unicode,height,0,nil,-height) + c.top_accent = nil return c end diff --git a/tex/context/base/math-fen.mkiv b/tex/context/base/math-fen.mkiv index fe959cc1e..94d93e4af 100644 --- a/tex/context/base/math-fen.mkiv +++ b/tex/context/base/math-fen.mkiv @@ -144,7 +144,7 @@ \definemathfence [mirroredangle] [mirrored] [\c!right="27E8,\c!left="27E9] \definemathfence [mirroreddoubleangle] [mirrored] [\c!right="27EA,\c!left="27EB] \definemathfence [mirroredsolidus] [mirrored] [\c!right="2044,\c!left="2044] -\definemathfence [mirrorednothing] [mirrored] +\definemathfence [mirrorednothing] [mirorred] %D A bonus: diff --git a/tex/context/base/math-ini.lua b/tex/context/base/math-ini.lua index 1351559a0..6be06e634 100644 --- a/tex/context/base/math-ini.lua +++ b/tex/context/base/math-ini.lua @@ -350,12 +350,10 @@ local utf8byte = lpeg.patterns.utf8byte * lpeg.P(-1) local somechar = { } table.setmetatableindex(somechar,function(t,k) - if k then - local b = lpegmatch(utf8byte,k) - local v = b and chardata[b] or false - t[k] = v - return v - end + local b = lpegmatch(utf8byte,k) + local v = b and chardata[b] or false + t[k] = v + return v end) local function utfmathclass(chr, default) @@ -472,7 +470,6 @@ mathematics.utfmathclass = utfmathclass mathematics.utfmathstretch = utfmathstretch mathematics.utfmathcommand = utfmathcommand mathematics.utfmathfiller = utfmathfiller -mathematics.utfmathaccent = utfmathaccent -- interfaced diff --git a/tex/context/base/math-noa.lua b/tex/context/base/math-noa.lua index 4e25fe206..f3987c12f 100644 --- a/tex/context/base/math-noa.lua +++ b/tex/context/base/math-noa.lua @@ -54,35 +54,16 @@ local report_families = logs.reporter("mathematics","families") local a_mathrendering = attributes.private("mathrendering") local a_exportstatus = attributes.private("exportstatus") -local nuts = nodes.nuts -local nodepool = nuts.pool -local tonut = nuts.tonut -local nutstring = nuts.tostring - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before -local free_node = nuts.free -local new_node = nuts.new -- todo: pool: math_noad math_sub -local copy_node = nuts.copy - -local mlist_to_hlist = nodes.mlist_to_hlist - +local mlist_to_hlist = node.mlist_to_hlist local font_of_family = node.family_font +local insert_node_after = node.insert_after +local insert_node_before = node.insert_before +local free_node = node.free +local new_node = node.new -- todo: pool: math_noad math_sub +local copy_node = node.copy -local new_kern = nodepool.kern -local new_rule = nodepool.rule +local new_kern = nodes.pool.kern +local new_rule = nodes.pool.rule local topoints = number.points @@ -145,23 +126,23 @@ local function process(start,what,n,parent) if n then n = n + 1 else n = 0 end local prev = nil while start do - local id = getid(start) + local id = start.id if trace_processing then if id == math_noad then - report_processing("%w%S, class %a",n*2,nutstring(start),noadcodes[getsubtype(start)]) + report_processing("%w%S, class %a",n*2,start,noadcodes[start.subtype]) elseif id == math_char then - local char = getchar(start) - local fam = getfield(start,"fam") + local char = start.char + local fam = start.fam local font = font_of_family(fam) - report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,nutstring(start),fam,font,char,char) + report_processing("%w%S, family %a, font %a, char %a, shape %c",n*2,start,fam,font,char,char) else - report_processing("%w%S",n*2,nutstring(start)) + report_processing("%w%S",n*2,start) end end local proc = what[id] if proc then -- report_processing("start processing") - local done, newstart = proc(start,what,n,parent) -- prev is bugged: or getprev(start) + local done, newstart = proc(start,what,n,parent) -- prev is bugged: or start.prev if newstart then start = newstart -- report_processing("stop processing (new start)") @@ -173,55 +154,55 @@ local function process(start,what,n,parent) elseif id == math_noad then if prev then -- we have no proper prev in math nodes yet - setfield(start,"prev",prev) + start.prev = prev end - - local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"sub") if noad then process(noad,what,n,start) end -- list + local noad = start.nucleus if noad then process(noad,what,n,start) end -- list + noad = start.sup if noad then process(noad,what,n,start) end -- list + noad = start.sub if noad then process(noad,what,n,start) end -- list elseif id == math_box or id == math_sub then - local noad = getfield(start,"list") if noad then process(noad,what,n,start) end -- list (not getlist !) + -- local noad = start.list if noad then process(noad,what,n,start) end -- list + local noad = start.head if noad then process(noad,what,n,start) end -- list elseif id == math_fraction then - local noad = getfield(start,"num") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"denom") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter - noad = getfield(start,"right") if noad then process(noad,what,n,start) end -- delimiter + local noad = start.num if noad then process(noad,what,n,start) end -- list + noad = start.denom if noad then process(noad,what,n,start) end -- list + noad = start.left if noad then process(noad,what,n,start) end -- delimiter + noad = start.right if noad then process(noad,what,n,start) end -- delimiter elseif id == math_choice then - local noad = getfield(start,"display") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"text") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"script") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"scriptscript") if noad then process(noad,what,n,start) end -- list + local noad = start.display if noad then process(noad,what,n,start) end -- list + noad = start.text if noad then process(noad,what,n,start) end -- list + noad = start.script if noad then process(noad,what,n,start) end -- list + noad = start.scriptscript if noad then process(noad,what,n,start) end -- list elseif id == math_fence then - local noad = getfield(start,"delim") if noad then process(noad,what,n,start) end -- delimiter + local noad = start.delim if noad then process(noad,what,n,start) end -- delimiter elseif id == math_radical then - local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"sub") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"left") if noad then process(noad,what,n,start) end -- delimiter - noad = getfield(start,"degree") if noad then process(noad,what,n,start) end -- list + local noad = start.nucleus if noad then process(noad,what,n,start) end -- list + noad = start.sup if noad then process(noad,what,n,start) end -- list + noad = start.sub if noad then process(noad,what,n,start) end -- list + noad = start.left if noad then process(noad,what,n,start) end -- delimiter + noad = start.degree if noad then process(noad,what,n,start) end -- list elseif id == math_accent then - local noad = getfield(start,"nucleus") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"sup") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"sub") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"accent") if noad then process(noad,what,n,start) end -- list - noad = getfield(start,"bot_accent") if noad then process(noad,what,n,start) end -- list + local noad = start.nucleus if noad then process(noad,what,n,start) end -- list + noad = start.sup if noad then process(noad,what,n,start) end -- list + noad = start.sub if noad then process(noad,what,n,start) end -- list + noad = start.accent if noad then process(noad,what,n,start) end -- list + noad = start.bot_accent if noad then process(noad,what,n,start) end -- list elseif id == math_style then -- has a next else -- glue, penalty, etc end prev = start - start = getnext(start) + start = start.next end end local function processnoads(head,actions,banner) if trace_processing then report_processing("start %a",banner) - process(tonut(head),actions) + process(head,actions) report_processing("stop %a",banner) else - process(tonut(head),actions) + process(head,actions) end end @@ -252,71 +233,37 @@ local familymap = { [0] = "pseudobold", } --- families[math_char] = function(pointer) --- if getfield(pointer,"fam") == 0 then --- local a = getattr(pointer,a_mathfamily) --- if a and a > 0 then --- setattr(pointer,a_mathfamily,0) --- if a > 5 then --- local char = getchar(pointer) --- local bold = boldmap[char] --- local newa = a - 3 --- if bold then --- setattr(pointer,a_exportstatus,char) --- setfield(pointer,"char",bold) --- if trace_families then --- report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa]) --- end --- else --- if trace_families then --- report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) --- end --- end --- setfield(pointer,"fam",newa) --- else --- if trace_families then --- local char = getchar(pointer) --- report_families("family of %C becomes %s with remap %s",char,a,familymap[a]) --- end --- setfield(pointer,"fam",a) --- end --- else --- -- pointer.fam = 0 --- end --- end --- end - families[math_char] = function(pointer) - if getfield(pointer,"fam") == 0 then - local a = getattr(pointer,a_mathfamily) + if pointer.fam == 0 then + local a = pointer[a_mathfamily] if a and a > 0 then - setattr(pointer,a_mathfamily,0) + pointer[a_mathfamily] = 0 if a > 5 then - local char = getchar(pointer) + local char = pointer.char local bold = boldmap[char] local newa = a - 3 if not bold then if trace_families then report_families("no bold replacement for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) end - setfield(pointer,"fam",newa) - elseif not fontcharacters[font_of_family(newa)][bold] then + pointer.fam = newa + elseif not fontcharacters[font_of_family(newa)][bold] then if trace_families then report_families("no bold character for %C, family %s with remap %s becomes %s with remap %s",char,a,familymap[a],newa,familymap[newa]) end if newa > 3 then - setfield(pointer,"fam",newa-3) + pointer.fam = newa - 3 end else - setattr(pointer,a_exportstatus,char) - setfield(pointer,"char",bold) + pointer[a_exportstatus] = char + pointer.char = bold if trace_families then report_families("replacing %C by bold %C, family %s with remap %s becomes %s with remap %s",char,bold,a,familymap[a],newa,familymap[newa]) end - setfield(pointer,"fam",newa) + pointer.fam = newa end else - local char = getchar(pointer) + local char = pointer.char if not fontcharacters[font_of_family(a)][char] then if trace_families then report_families("no bold replacement for %C",char) @@ -325,7 +272,7 @@ families[math_char] = function(pointer) if trace_families then report_families("family of %C becomes %s with remap %s",char,a,familymap[a]) end - setfield(pointer,"fam",a) + pointer.fam = a end end end @@ -333,31 +280,31 @@ families[math_char] = function(pointer) end families[math_delim] = function(pointer) - if getfield(pointer,"small_fam") == 0 then - local a = getattr(pointer,a_mathfamily) + if pointer.small_fam == 0 then + local a = pointer[a_mathfamily] if a and a > 0 then - setattr(pointer,a_mathfamily,0) + pointer[a_mathfamily] = 0 if a > 5 then -- no bold delimiters in unicode a = a - 3 end - local char = getfield(pointer,"small_char") + local char = pointer.small_char local okay = fontcharacters[font_of_family(a)][char] if okay then - setfield(pointer,"small_fam",a) + pointer.small_fam = a elseif a > 2 then - setfield(pointer,"small_fam",a-3) + pointer.small_fam = a - 3 end - local char = getfield(pointer,"large_char") + local char = pointer.large_char local okay = fontcharacters[font_of_family(a)][char] if okay then - setfield(pointer,"large_fam",a) + pointer.large_fam = a elseif a > 2 then - setfield(pointer,"large_fam",a-3) + pointer.large_fam = a - 3 end else - setfield(pointer,"small_fam",0) - setfield(pointer,"large_fam",0) + pointer.small_fam = 0 + pointer.large_fam = 0 end end end @@ -385,8 +332,8 @@ local fallbackstyleattr = mathematics.fallbackstyleattr local setnodecolor = nodes.tracers.colors.set local function checked(pointer) - local char = getchar(pointer) - local fam = getfield(pointer,"fam") + local char = pointer.char + local fam = pointer.fam local id = font_of_family(fam) local tc = fontcharacters[id] if not tc[char] then @@ -399,27 +346,27 @@ local function checked(pointer) if trace_analyzing then setnodecolor(pointer,"font:isol") end - setattr(pointer,a_exportstatus,char) -- testcase: exponentiale - setfield(pointer,"char",newchar) + pointer[a_exportstatus] = char -- testcase: exponentiale + pointer.char = newchar return true end end end processors.relocate[math_char] = function(pointer) - local g = getattr(pointer,a_mathgreek) or 0 - local a = getattr(pointer,a_mathalphabet) or 0 + local g = pointer[a_mathgreek] or 0 + local a = pointer[a_mathalphabet] or 0 if a > 0 or g > 0 then if a > 0 then - setattr(pointer,a_mathgreek,0) + pointer[a_mathgreek] = 0 end if g > 0 then - setattr(pointer,a_mathalphabet,0) + pointer[a_mathalphabet] = 0 end - local char = getchar(pointer) + local char = pointer.char local newchar = remapalphabets(char,a,g) if newchar then - local fam = getfield(pointer,"fam") + local fam = pointer.fam local id = font_of_family(fam) local characters = fontcharacters[id] if characters[newchar] then @@ -429,7 +376,7 @@ processors.relocate[math_char] = function(pointer) if trace_analyzing then setnodecolor(pointer,"font:isol") end - setfield(pointer,"char",newchar) + pointer.char = newchar return true else local fallback = fallbackstyleattr(a) @@ -443,7 +390,7 @@ processors.relocate[math_char] = function(pointer) if trace_analyzing then setnodecolor(pointer,"font:isol") end - setfield(pointer,"char",newchar) + pointer.char = newchar return true elseif trace_remapping then report_remap("char",id,char,newchar," fails (no fallback character)") @@ -489,19 +436,19 @@ processors.render = { } local rendersets = mathematics.renderings.numbers or { } -- store processors.render[math_char] = function(pointer) - local attr = getattr(pointer,a_mathrendering) + local attr = pointer[a_mathrendering] if attr and attr > 0 then - local char = getchar(pointer) + local char = pointer.char local renderset = rendersets[attr] if renderset then local newchar = renderset[char] if newchar then - local fam = getfield(pointer,"fam") + local fam = pointer.fam local id = font_of_family(fam) local characters = fontcharacters[id] if characters and characters[newchar] then - setfield(pointer,"char",newchar) - setattr(pointer,a_exportstatus,char) + pointer.char = newchar + pointer[a_exportstatus] = char end end end @@ -528,19 +475,19 @@ local mathsize = attributes.private("mathsize") local resize = { } processors.resize = resize resize[math_fence] = function(pointer) - local subtype = getsubtype(pointer) + local subtype = pointer.subtype if subtype == left_fence_code or subtype == right_fence_code then - local a = getattr(pointer,mathsize) + local a = pointer[mathsize] if a and a > 0 then local method, size = div(a,100), a % 100 - setattr(pointer,mathsize,0) - local delimiter = getfield(pointer,"delim") - local chr = getfield(delimiter,"small_char") + pointer[mathsize] = 0 + local delimiter = pointer.delim + local chr = delimiter.small_char if chr > 0 then - local fam = getfield(delimiter,"small_fam") + local fam = delimiter.small_fam local id = font_of_family(fam) if id > 0 then - setfield(delimiter,"small_char",mathematics.big(fontdata[id],chr,size,method)) + delimiter.small_char = mathematics.big(fontdata[id],chr,size,method) end end end @@ -552,6 +499,7 @@ function handlers.resize(head,style,penalties) return true end + local collapse = { } processors.collapse = collapse local mathpairs = characters.mathpairs @@ -590,20 +538,20 @@ local validpair = { } local function movesubscript(parent,current_nucleus,current_char) - local prev = getfield(parent,"prev") - if prev and getid(prev) == math_noad then - if not getfield(prev,"sup") and not getfield(prev,"sub") then - setfield(current_nucleus,"char",movesub[current_char or getchar(current_nucleus)]) + local prev = parent.prev + if prev and prev.id == math_noad then + if not prev.sup and not prev.sub then + current_nucleus.char = movesub[current_char or current_nucleus.char] -- {f} {'}_n => f_n^' - local nucleus = getfield(parent,"nucleus") - local sub = getfield(parent,"sub") - local sup = getfield(parent,"sup") - setfield(prev,"sup",nucleus) - setfield(prev,"sub",sub) + local nucleus = parent.nucleus + local sub = parent.sub + local sup = parent.sup + prev.sup = nucleus + prev.sub = sub local dummy = copy_node(nucleus) - setfield(dummy,"char",0) - setfield(parent,"nucleus",dummy) - setfield(parent,"sub",nil) + dummy.char = 0 + parent.nucleus = dummy + parent.sub = nil if trace_collapsing then report_collapsing("fixing subscript") end @@ -613,40 +561,40 @@ end local function collapsepair(pointer,what,n,parent,nested) -- todo: switch to turn in on and off if parent then - if validpair[getsubtype(parent)] then - local current_nucleus = getfield(parent,"nucleus") - if getid(current_nucleus) == math_char then - local current_char = getchar(current_nucleus) - if not getfield(parent,"sub") and not getfield(parent,"sup") then + if validpair[parent.subtype] then + local current_nucleus = parent.nucleus + if current_nucleus.id == math_char then + local current_char = current_nucleus.char + if not parent.sub and not parent.sup then local mathpair = mathpairs[current_char] if mathpair then - local next_noad = getnext(parent) - if next_noad and getid(next_noad) == math_noad then - if validpair[getsubtype(next_noad)] then - local next_nucleus = getfield(next_noad,"nucleus") - if getid(next_nucleus) == math_char then - local next_char = getchar(next_nucleus) + local next_noad = parent.next + if next_noad and next_noad.id == math_noad then + if validpair[next_noad.subtype] then + local next_nucleus = next_noad.nucleus + if next_nucleus.id == math_char then + local next_char = next_nucleus.char local newchar = mathpair[next_char] if newchar then - local fam = getfield(current_nucleus,"fam") + local fam = current_nucleus.fam local id = font_of_family(fam) local characters = fontcharacters[id] if characters and characters[newchar] then if trace_collapsing then report_collapsing("%U + %U => %U",current_char,next_char,newchar) end - setfield(current_nucleus,"char",newchar) - local next_next_noad = getnext(next_noad) + current_nucleus.char = newchar + local next_next_noad = next_noad.next if next_next_noad then - setfield(parent,"next",next_next_noad) - setfield(next_next_noad,"prev",parent) + parent.next = next_next_noad + next_next_noad.prev = parent else - setfield(parent,"next",nil) + parent.next = nil end - setfield(parent,"sup",getfield(next_noad,"sup")) - setfield(parent,"sub",getfield(next_noad,"sub")) - setfield(next_noad,"sup",nil) - setfield(next_noad,"sub",nil) + parent.sup = next_noad.sup + parent.sub = next_noad.sub + next_noad.sup = nil + next_noad.sub = nil free_node(next_noad) collapsepair(pointer,what,n,parent,true) if not nested and movesub[current_char] then @@ -686,13 +634,13 @@ local replaced = { } local function replace(pointer,what,n,parent) pointer = parent -- we're following the parent list (chars trigger this) - local next = getnext(pointer) + local next = pointer.next local start_super, stop_super, start_sub, stop_sub local mode = "unset" - while next and getid(next) == math_noad do - local nextnucleus = getfield(next,"nucleus") - if nextnucleus and getid(nextnucleus) == math_char and not getfield(next,"sub") and not getfield(next,"sup") then - local char = getchar(nextnucleus) + while next and next.id == math_noad do + local nextnucleus = next.nucleus + if nextnucleus and nextnucleus.id == math_char and not next.sub and not next.sup then + local char = nextnucleus.char local s = superscripts[char] if s then if not start_super then @@ -702,8 +650,8 @@ local function replace(pointer,what,n,parent) break end stop_super = next - next = getnext(next) - setfield(nextnucleus,"char",s) + next = next.next + nextnucleus.char = s replaced[char] = (replaced[char] or 0) + 1 if trace_normalizing then report_normalizing("superscript %C becomes %C",char,s) @@ -718,8 +666,8 @@ local function replace(pointer,what,n,parent) break end stop_sub = next - next = getnext(next) - setfield(nextnucleus,"char",s) + next = next.next + nextnucleus.char = s replaced[char] = (replaced[char] or 0) + 1 if trace_normalizing then report_normalizing("subscript %C becomes %C",char,s) @@ -734,29 +682,29 @@ local function replace(pointer,what,n,parent) end if start_super then if start_super == stop_super then - setfield(pointer,"sup",getfield(start_super,"nucleus")) + pointer.sup = start_super.nucleus else local list = new_node(math_sub) -- todo attr - setfield(list,"list",start_super) - setfield(pointer,"sup",list) + list.head = start_super + pointer.sup = list end if mode == "super" then - setfield(pointer,"next",getnext(stop_super)) + pointer.next = stop_super.next end - setfield(stop_super,"next",nil) + stop_super.next = nil end if start_sub then if start_sub == stop_sub then - setfield(pointer,"sub",getfield(start_sub,"nucleus")) + pointer.sub = start_sub.nucleus else local list = new_node(math_sub) -- todo attr - setfield(list,"list",start_sub) - setfield(pointer,"sub",list) + list.head = start_sub + pointer.sub = list end if mode == "sub" then - setfield(pointer,"next",getnext(stop_sub)) + pointer.next = stop_sub.next end - setfield(stop_sub,"next",nil) + stop_sub.next = nil end -- we could return stop end @@ -837,20 +785,20 @@ function mathematics.setalternate(fam,tag) end alternate[math_char] = function(pointer) - local a = getattr(pointer,a_mathalternate) + local a = pointer[a_mathalternate] if a and a > 0 then - setattr(pointer,a_mathalternate,0) - local tfmdata = fontdata[font_of_family(getfield(pointer,"fam"))] -- we can also have a famdata + pointer[a_mathalternate] = 0 + local tfmdata = fontdata[font_of_family(pointer.fam)] -- we can also have a famdata local mathalternatesattributes = tfmdata.shared.mathalternatesattributes if mathalternatesattributes then local what = mathalternatesattributes[a] - local alt = getalternate(tfmdata,getchar(pointer),what.feature,what.value) + local alt = getalternate(tfmdata,pointer.char,what.feature,what.value) if alt then if trace_alternates then report_alternates("alternate %a, value %a, replacing glyph %U by glyph %U", - tostring(what.feature),tostring(what.value),getchar(pointer),alt) + tostring(what.feature),tostring(what.value),pointer.char,alt) end - setfield(pointer,"char",alt) + pointer.char = alt end end end @@ -937,14 +885,13 @@ end local function insert_kern(current,kern) local sub = new_node(math_sub) -- todo: pool local noad = new_node(math_noad) -- todo: pool - setfield(sub,"list",kern) - setfield(kern,"next",noad) - setfield(noad,"nucleus",current) + sub.head = kern + kern.next = noad + noad.nucleus = current return sub end local setcolor = nodes.tracers.colors.set -local resetcolor = nodes.tracers.colors.reset local italic_kern = new_kern local c_positive_d = "trace:db" local c_negative_d = "trace:dr" @@ -966,44 +913,44 @@ trackers.register("math.italics", function(v) end) italics[math_char] = function(pointer,what,n,parent) - local method = getattr(pointer,a_mathitalics) + local method = pointer[a_mathitalics] if method and method > 0 then - local char = getchar(pointer) - local font = font_of_family(getfield(pointer,"fam")) -- todo: table + local char = pointer.char + local font = font_of_family(pointer.fam) -- todo: table local correction, visual = getcorrection(method,font,char) if correction then - local pid = getid(parent) + local pid = parent.id local sub, sup if pid == math_noad then - sup = getfield(parent,"sup") - sub = getfield(parent,"sub") + sup = parent.sup + sub = parent.sub end if sup or sub then - local subtype = getsubtype(parent) + local subtype = parent.subtype if subtype == noad_oplimits then if sup then - setfield(parent,"sup",insert_kern(sup,italic_kern(correction,font))) + parent.sup = insert_kern(sup,italic_kern(correction,font)) if trace_italics then report_italics("method %a, adding %p italic correction for upper limit of %C",method,correction,char) end end if sub then local correction = - correction - setfield(parent,"sub",insert_kern(sub,italic_kern(correction,font))) + parent.sub = insert_kern(sub,italic_kern(correction,font)) if trace_italics then report_italics("method %a, adding %p italic correction for lower limit of %C",method,correction,char) end end else if sup then - setfield(parent,"sup",insert_kern(sup,italic_kern(correction,font))) + parent.sup = insert_kern(sup,italic_kern(correction,font)) if trace_italics then report_italics("method %a, adding %p italic correction before superscript after %C",method,correction,char) end end end else - local next_noad = getnext(parent) + local next_noad = parent.next if not next_noad then if n== 1 then -- only at the outer level .. will become an option (always,endonly,none) if trace_italics then @@ -1011,12 +958,12 @@ italics[math_char] = function(pointer,what,n,parent) end insert_node_after(parent,parent,italic_kern(correction,font)) end - elseif getid(next_noad) == math_noad then - local next_subtype = getsubtype(next_noad) + elseif next_noad.id == math_noad then + local next_subtype = next_noad.subtype if next_subtype == noad_punct or next_subtype == noad_ord then - local next_nucleus = getfield(next_noad,"nucleus") - if getid(next_nucleus) == math_char then - local next_char = getchar(next_nucleus) + local next_nucleus = next_noad.nucleus + if next_nucleus.id == math_char then + local next_char = next_nucleus.char local next_data = chardata[next_char] local visual = next_data.visual if visual == "it" or visual == "bi" then @@ -1100,15 +1047,15 @@ local validvariants = { -- fast check on valid } variants[math_char] = function(pointer,what,n,parent) -- also set export value - local char = getchar(pointer) + local char = pointer.char local selector = validvariants[char] if selector then - local next = getnext(parent) - if next and getid(next) == math_noad then - local nucleus = getfield(next,"nucleus") - if nucleus and getid(nucleus) == math_char and getchar(nucleus) == selector then + local next = parent.next + if next and next.id == math_noad then + local nucleus = next.nucleus + if nucleus and nucleus.id == math_char and nucleus.char == selector then local variant - local tfmdata = fontdata[font_of_family(getfield(pointer,"fam"))] -- we can also have a famdata + local tfmdata = fontdata[font_of_family(pointer.fam)] -- we can also have a famdata local mathvariants = tfmdata.resources.variants -- and variantdata if mathvariants then mathvariants = mathvariants[selector] @@ -1117,8 +1064,8 @@ variants[math_char] = function(pointer,what,n,parent) -- also set export value end end if variant then - setfield(pointer,"char",variant) - setattr(pointer,a_exportstatus,char) -- we don't export the variant as it's visual markup + pointer.char = variant + pointer[a_exportstatus] = char -- we don't export the variant as it's visual markup if trace_variants then report_variants("variant (%U,%U) replaced by %U",char,selector,variant) end @@ -1127,8 +1074,8 @@ variants[math_char] = function(pointer,what,n,parent) -- also set export value report_variants("no variant (%U,%U)",char,selector) end end - setfield(next,"prev",pointer) - setfield(parent,"next",getnext(next)) + next.prev = pointer + parent.next = next.next free_node(next) end end @@ -1161,7 +1108,7 @@ local colors = { } classes[math_char] = function(pointer,what,n,parent) - local color = colors[getsubtype(parent)] + local color = colors[parent.subtype] if color then setcolor(pointer,color) else diff --git a/tex/context/base/math-tag.lua b/tex/context/base/math-tag.lua index 3cd4cae16..ab5902dd4 100644 --- a/tex/context/base/math-tag.lua +++ b/tex/context/base/math-tag.lua @@ -11,22 +11,10 @@ if not modules then modules = { } end modules ['math-tag'] = { local find, match = string.find, string.match local insert, remove = table.insert, table.remove -local attributes = attributes -local nodes = nodes +local attributes, nodes = attributes, nodes -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getid = nuts.getid -local getchar = nuts.getchar -local getlist = nuts.getlist -local getfield = nuts.getfield -local getattr = nuts.getattr -local setattr = nuts.setattr - -local set_attributes = nuts.setattributes -local traverse_nodes = nuts.traverse +local set_attributes = nodes.setattributes +local traverse_nodes = node.traverse local nodecodes = nodes.nodecodes @@ -73,24 +61,22 @@ local function processsubsup(start) -- At some point we might need to add an attribute signaling the -- super- and subscripts because TeX and MathML use a different -- order. - local nucleus = getfield(start,"nucleus") - local sup = getfield(start,"sup") - local sub = getfield(start,"sub") + local nucleus, sup, sub = start.nucleus, start.sup, start.sub if sub then if sup then - setattr(start,a_tagged,start_tagged("msubsup")) + start[a_tagged] = start_tagged("msubsup") process(nucleus) process(sub) process(sup) stop_tagged() else - setattr(start,a_tagged,start_tagged("msub")) + start[a_tagged] = start_tagged("msub") process(nucleus) process(sub) stop_tagged() end elseif sup then - setattr(start,a_tagged,start_tagged("msup")) + start[a_tagged] = start_tagged("msup") process(nucleus) process(sup) stop_tagged() @@ -107,11 +93,11 @@ local actionstack = { } process = function(start) -- we cannot use the processor as we have no finalizers (yet) while start do - local id = getid(start) + local id = start.id if id == math_char_code then - local char = getchar(start) + local char = start.char -- check for code - local a = getattr(start,a_mathcategory) + local a = start[a_mathcategory] if a then a = { detail = a } end @@ -133,22 +119,22 @@ process = function(start) -- we cannot use the processor as we have no finalizer else tag = "mo" end - setattr(start,a_tagged,start_tagged(tag,a)) + start[a_tagged] = start_tagged(tag,a) stop_tagged() break -- okay? elseif id == math_textchar_code then -- check for code - local a = getattr(start,a_mathcategory) + local a = start[a_mathcategory] if a then - setattr(start,a_tagged,start_tagged("ms",{ detail = a })) + start[a_tagged] = start_tagged("ms",{ detail = a }) else - setattr(start,a_tagged,start_tagged("ms")) + start[a_tagged] = start_tagged("ms") end stop_tagged() break elseif id == math_delim_code then -- check for code - setattr(start,a_tagged,start_tagged("mo")) + start[a_tagged] = start_tagged("mo") stop_tagged() break elseif id == math_style_code then @@ -157,14 +143,14 @@ process = function(start) -- we cannot use the processor as we have no finalizer processsubsup(start) elseif id == math_box_code or id == hlist_code or id == vlist_code then -- keep an eye on math_box_code and see what ends up in there - local attr = getattr(start,a_tagged) + local attr = start[a_tagged] local last = attr and taglist[attr] if last and find(last[#last],"formulacaption[:%-]") then -- leave alone, will nicely move to the outer level else local text = start_tagged("mtext") - setattr(start,a_tagged,text) - local list = getfield(start,"list") + start[a_tagged] = text + local list = start.list if not list then -- empty list elseif not attr then @@ -180,8 +166,8 @@ process = function(start) -- we cannot use the processor as we have no finalizer local function runner(list) -- quite inefficient local cache = { } -- we can have nested unboxed mess so best local to runner for n in traverse_nodes(list) do - local id = getid(n) - local aa = getattr(n,a_tagged) + local id = n.id + local aa = n[a_tagged] if aa then local ac = cache[aa] if not ac then @@ -199,12 +185,12 @@ process = function(start) -- we cannot use the processor as we have no finalizer end cache[aa] = ac end - setattr(n,a_tagged,ac) + n[a_tagged] = ac else - setattr(n,a_tagged,text) + n[a_tagged] = text end if id == hlist_code or id == vlist_code then - runner(getlist(n)) + runner(n.list) end end end @@ -213,53 +199,47 @@ process = function(start) -- we cannot use the processor as we have no finalizer stop_tagged() end elseif id == math_sub_code then - local list = getfield(start,"list") + local list = start.list if list then - local attr = getattr(start,a_tagged) + local attr = start[a_tagged] local last = attr and taglist[attr] local action = last and match(last[#last],"maction:(.-)%-") if action and action ~= "" then if actionstack[#actionstack] == action then - setattr(start,a_tagged,start_tagged("mrow")) + start[a_tagged] = start_tagged("mrow") process(list) stop_tagged() else insert(actionstack,action) - setattr(start,a_tagged,start_tagged("mrow",{ detail = action })) + start[a_tagged] = start_tagged("mrow",{ detail = action }) process(list) stop_tagged() remove(actionstack) end else - setattr(start,a_tagged,start_tagged("mrow")) + start[a_tagged] = start_tagged("mrow") process(list) stop_tagged() end end elseif id == math_fraction_code then - local num = getfield(start,"num") - local denom = getfield(start,"denom") - local left = getfield(start,"left") - local right = getfield(start,"right") + local num, denom, left, right = start.num, start.denom, start.left, start.right if left then - setattr(left,a_tagged,start_tagged("mo")) + left[a_tagged] = start_tagged("mo") process(left) stop_tagged() end - setattr(start,a_tagged,start_tagged("mfrac")) + start[a_tagged] = start_tagged("mfrac") process(num) process(denom) stop_tagged() if right then - setattr(right,a_tagged,start_tagged("mo")) + right[a_tagged] = start_tagged("mo") process(right) stop_tagged() end elseif id == math_choice_code then - local display = getfield(start,"display") - local text = getfield(start,"text") - local script = getfield(start,"script") - local scriptscript = getfield(start,"scriptscript") + local display, text, script, scriptscript = start.display, start.text, start.script, start.scriptscript if display then process(display) end @@ -273,69 +253,67 @@ process = function(start) -- we cannot use the processor as we have no finalizer process(scriptscript) end elseif id == math_fence_code then - local delim = getfield(start,"delim") - local subtype = getfield(start,"subtype") - -- setattr(start,a_tagged,start_tagged("mfenced")) -- needs checking + local delim = start.delim + local subtype = start.subtype if subtype == 1 then -- left + start[a_tagged] = start_tagged("mfenced") if delim then - setattr(start,a_tagged,start_tagged("mleft")) + start[a_tagged] = start_tagged("mleft") process(delim) stop_tagged() end elseif subtype == 2 then -- middle if delim then - setattr(start,a_tagged,start_tagged("mmiddle")) + start[a_tagged] = start_tagged("mmiddle") process(delim) stop_tagged() end elseif subtype == 3 then if delim then - setattr(start,a_tagged,start_tagged("mright")) + start[a_tagged] = start_tagged("mright") process(delim) stop_tagged() end + stop_tagged() else -- can't happen end - -- stop_tagged() elseif id == math_radical_code then - local left = getfield(start,"left") - local degree = getfield(start,"degree") + local left, degree = start.left, start.degree if left then start_tagged("") process(left) -- root symbol, ignored stop_tagged() end if degree then -- not good enough, can be empty mlist - setattr(start,a_tagged,start_tagged("mroot")) + start[a_tagged] = start_tagged("mroot") processsubsup(start) process(degree) stop_tagged() else - setattr(start,a_tagged,start_tagged("msqrt")) + start[a_tagged] = start_tagged("msqrt") processsubsup(start) stop_tagged() end elseif id == math_accent_code then - local accent = getfield(start,"accent") - local bot_accent = getfield(start,"bot_accent") + local accent, bot_accent = start.accent, start.bot_accent if bot_accent then if accent then - setattr(start,a_tagged,start_tagged("munderover",{ detail = "accent" })) + start[a_tagged] = start_tagged("munderover",{ detail = "accent" }) processsubsup(start) process(bot_accent) process(accent) stop_tagged() else - setattr(start,a_tagged,start_tagged("munder",{ detail = "accent" })) + start[a_tagged] = start_tagged("munder",{ detail = "accent" }) processsubsup(start) process(bot_accent) stop_tagged() end elseif accent then - setattr(start,a_tagged,start_tagged("mover",{ detail = "accent" })) + start[a_tagged] = start_tagged("mover",{ detail = "accent" }) processsubsup(start) process(accent) stop_tagged() @@ -343,23 +321,22 @@ process = function(start) -- we cannot use the processor as we have no finalizer processsubsup(start) end elseif id == glue_code then - setattr(start,a_tagged,start_tagged("mspace")) + start[a_tagged] = start_tagged("mspace") stop_tagged() else - setattr(start,a_tagged,start_tagged("merror", { detail = nodecodes[i] })) + start[a_tagged] = start_tagged("merror", { detail = nodecodes[i] }) stop_tagged() end - start = getnext(start) + start = start.next end end function noads.handlers.tags(head,style,penalties) - head = tonut(head) local v_math = start_tagged("math") local v_mrow = start_tagged("mrow") - local v_mode = getattr(head,a_mathmode) - -- setattr(head,a_tagged,v_math) - setattr(head,a_tagged,v_mrow) + local v_mode = head[a_mathmode] + head[a_tagged] = v_math + head[a_tagged] = v_mrow tags.setattributehash(v_math,"mode",v_mode == 1 and "display" or "inline") process(head) stop_tagged() diff --git a/tex/context/base/mult-de.mkii b/tex/context/base/mult-de.mkii index 0c4dae5b6..5f2714ce6 100644 --- a/tex/context/base/mult-de.mkii +++ b/tex/context/base/mult-de.mkii @@ -1045,8 +1045,6 @@ \setinterfaceconstant{suffix}{suffix} \setinterfaceconstant{suffixseparator}{suffixseparator} \setinterfaceconstant{suffixstopper}{suffixstopper} -\setinterfaceconstant{surnamefirstnamesep}{surnamefirstnamesep} -\setinterfaceconstant{surnameinitialsep}{surnameinitialsep} \setinterfaceconstant{surnamesep}{surnamesep} \setinterfaceconstant{sx}{sx} \setinterfaceconstant{sy}{sy} diff --git a/tex/context/base/mult-def.lua b/tex/context/base/mult-def.lua index 65db8fd5e..afd466531 100644 --- a/tex/context/base/mult-def.lua +++ b/tex/context/base/mult-def.lua @@ -6613,9 +6613,6 @@ return { ["firstnamesep"]={ ["en"]="firstnamesep", }, - ["surnamefirstnamesep"]={ - ["en"]="surnamefirstnamesep", - }, ["vonsep"]={ ["en"]="vonsep", }, @@ -6625,9 +6622,6 @@ return { ["surnamesep"]={ ["en"]="surnamesep", }, - ["surnameinitialsep"]={ - ["en"]="surnameinitialsep", - }, ["lastnamesep"]={ ["en"]="lastnamesep", }, diff --git a/tex/context/base/mult-def.mkiv b/tex/context/base/mult-def.mkiv index 9206743f4..192a380ee 100644 --- a/tex/context/base/mult-def.mkiv +++ b/tex/context/base/mult-def.mkiv @@ -36,7 +36,6 @@ \def\c!fences {fences} \def\c!keeptogether {keeptogether} -\def\c!viewerprefix {viewerprefix} \def\c!dataset {dataset} \def\c!sectionblock {sectionblock} @@ -54,7 +53,6 @@ \def\c!comma {comma} \def\c!period {period} \def\c!monthconversion {monthconversion} -\def\c!authorconversion {authorconversion} \def\c!comment {comment} \def\c!textalign {textalign} \def\c!up {up} @@ -64,7 +62,6 @@ \def\c!group {group} \def\c!groupsuffix {groupsuffix} -\def\v!dataset {dataset} \def\v!compressseparator{compressseparator} \def\v!notation {notation} \def\v!endnote {endnote} @@ -81,7 +78,6 @@ \def\v!combination {combination} \def\v!norepeat {norepeat} \def\v!mixed {mixed} -\def\v!centerlast {centerlast} \def\s!lcgreek {lcgreek} \def\s!ucgreek {ucgreek} diff --git a/tex/context/base/mult-en.mkii b/tex/context/base/mult-en.mkii index 00861c3be..97732dab7 100644 --- a/tex/context/base/mult-en.mkii +++ b/tex/context/base/mult-en.mkii @@ -1045,8 +1045,6 @@ \setinterfaceconstant{suffix}{suffix} \setinterfaceconstant{suffixseparator}{suffixseparator} \setinterfaceconstant{suffixstopper}{suffixstopper} -\setinterfaceconstant{surnamefirstnamesep}{surnamefirstnamesep} -\setinterfaceconstant{surnameinitialsep}{surnameinitialsep} \setinterfaceconstant{surnamesep}{surnamesep} \setinterfaceconstant{sx}{sx} \setinterfaceconstant{sy}{sy} diff --git a/tex/context/base/mult-fr.mkii b/tex/context/base/mult-fr.mkii index 9afe371c2..520f8e1a6 100644 --- a/tex/context/base/mult-fr.mkii +++ b/tex/context/base/mult-fr.mkii @@ -1045,8 +1045,6 @@ \setinterfaceconstant{suffix}{suffix} \setinterfaceconstant{suffixseparator}{suffixseparator} \setinterfaceconstant{suffixstopper}{suffixstopper} -\setinterfaceconstant{surnamefirstnamesep}{surnamefirstnamesep} -\setinterfaceconstant{surnameinitialsep}{surnameinitialsep} \setinterfaceconstant{surnamesep}{surnamesep} \setinterfaceconstant{sx}{sx} \setinterfaceconstant{sy}{sy} diff --git a/tex/context/base/mult-fun.lua b/tex/context/base/mult-fun.lua index 0f5bd8ace..2101b95e9 100644 --- a/tex/context/base/mult-fun.lua +++ b/tex/context/base/mult-fun.lua @@ -17,7 +17,7 @@ return { -- "sqr", "log", "ln", "exp", "inv", "pow", "pi", "radian", "tand", "cotd", "sin", "cos", "tan", "cot", "atan", "asin", "acos", - "invsin", "invcos", "invtan", "acosh", "asinh", "sinh", "cosh", + "invsin", "invcos", "acosh", "asinh", "sinh", "cosh", "paired", "tripled", "unitcircle", "fulldiamond", "unitdiamond", "fullsquare", -- "halfcircle", "quartercircle", diff --git a/tex/context/base/mult-it.mkii b/tex/context/base/mult-it.mkii index 802cb840c..2b31e8e10 100644 --- a/tex/context/base/mult-it.mkii +++ b/tex/context/base/mult-it.mkii @@ -1045,8 +1045,6 @@ \setinterfaceconstant{suffix}{suffix} \setinterfaceconstant{suffixseparator}{suffixseparator} \setinterfaceconstant{suffixstopper}{suffixstopper} -\setinterfaceconstant{surnamefirstnamesep}{surnamefirstnamesep} -\setinterfaceconstant{surnameinitialsep}{surnameinitialsep} \setinterfaceconstant{surnamesep}{surnamesep} \setinterfaceconstant{sx}{sx} \setinterfaceconstant{sy}{sy} diff --git a/tex/context/base/mult-low.lua b/tex/context/base/mult-low.lua index 250b20c22..f82be039c 100644 --- a/tex/context/base/mult-low.lua +++ b/tex/context/base/mult-low.lua @@ -279,9 +279,7 @@ return { -- "dorecurse", "doloop", "exitloop", "dostepwiserecurse", "recurselevel", "recursedepth", "dofastloopcs", "dowith", -- - "newconstant", "setnewconstant", "setconstant", "setconstantvalue", - "newconditional", "settrue", "setfalse", "settruevalue", "setfalsevalue", - -- + "newconstant", "setnewconstant", "newconditional", "settrue", "setfalse", "setconstant", "newmacro", "setnewmacro", "newfraction", "newsignal", -- @@ -367,7 +365,5 @@ return { -- "lesshyphens", "morehyphens", "nohyphens", "dohyphens", -- - "Ucheckedstartdisplaymath", "Ucheckedstopdisplaymath", - -- } } diff --git a/tex/context/base/mult-nl.mkii b/tex/context/base/mult-nl.mkii index a1f9742f1..9f91515cb 100644 --- a/tex/context/base/mult-nl.mkii +++ b/tex/context/base/mult-nl.mkii @@ -1045,8 +1045,6 @@ \setinterfaceconstant{suffix}{suffix} \setinterfaceconstant{suffixseparator}{suffixscheider} \setinterfaceconstant{suffixstopper}{suffixafsluiter} -\setinterfaceconstant{surnamefirstnamesep}{surnamefirstnamesep} -\setinterfaceconstant{surnameinitialsep}{surnameinitialsep} \setinterfaceconstant{surnamesep}{surnamesep} \setinterfaceconstant{sx}{sx} \setinterfaceconstant{sy}{sy} diff --git a/tex/context/base/mult-pe.mkii b/tex/context/base/mult-pe.mkii index 999b16cf5..240130cdf 100644 --- a/tex/context/base/mult-pe.mkii +++ b/tex/context/base/mult-pe.mkii @@ -1045,8 +1045,6 @@ \setinterfaceconstant{suffix}{پسوند} \setinterfaceconstant{suffixseparator}{suffixseparator} \setinterfaceconstant{suffixstopper}{suffixstopper} -\setinterfaceconstant{surnamefirstnamesep}{surnamefirstnamesep} -\setinterfaceconstant{surnameinitialsep}{surnameinitialsep} \setinterfaceconstant{surnamesep}{surnamesep} \setinterfaceconstant{sx}{sx} \setinterfaceconstant{sy}{sy} diff --git a/tex/context/base/mult-ro.mkii b/tex/context/base/mult-ro.mkii index f577eabda..3b7206e44 100644 --- a/tex/context/base/mult-ro.mkii +++ b/tex/context/base/mult-ro.mkii @@ -1045,8 +1045,6 @@ \setinterfaceconstant{suffix}{suffix} \setinterfaceconstant{suffixseparator}{suffixseparator} \setinterfaceconstant{suffixstopper}{suffixstopper} -\setinterfaceconstant{surnamefirstnamesep}{surnamefirstnamesep} -\setinterfaceconstant{surnameinitialsep}{surnameinitialsep} \setinterfaceconstant{surnamesep}{surnamesep} \setinterfaceconstant{sx}{sx} \setinterfaceconstant{sy}{sy} diff --git a/tex/context/base/node-acc.lua b/tex/context/base/node-acc.lua index 59fa031bf..81ae496b2 100644 --- a/tex/context/base/node-acc.lua +++ b/tex/context/base/node-acc.lua @@ -11,27 +11,10 @@ local nodes, node = nodes, node local nodecodes = nodes.nodecodes local tasks = nodes.tasks -local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode - -local getid = nuts.getid -local getfield = nuts.getfield -local getattr = nuts.getattr -local getlist = nuts.getlist -local getchar = nuts.getchar -local getnext = nuts.getnext - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local traverse_nodes = nuts.traverse -local traverse_id = nuts.traverse_id -local copy_node = nuts.copy -local free_nodelist = nuts.flush_list -local insert_after = nuts.insert_after - -local new_gluespec = nuts.pool.gluespec -- temp hack +local traverse_nodes = node.traverse +local traverse_id = node.traverse_id +local copy_node = node.copy +local free_nodelist = node.flush_list local glue_code = nodecodes.glue local kern_code = nodecodes.kern @@ -46,72 +29,57 @@ local threshold = 65536 -- todo: nbsp etc -- todo: collapse kerns --- p_id - local function injectspaces(head) - local p, p_id + local p local n = head while n do - local id = getid(n) + local id = n.id if id == glue_code then -- todo: check for subtype related to spacing (13/14 but most seems to be 0) - -- if getfield(getfield(n,"spec"),"width") > 0 then -- threshold --- if p and p_id == glyph_code then - if p and getid(p) == glyph_code then + -- if n.spec.width > 0 then -- threshold + if p and p.id == glyph_code then local g = copy_node(p) - local c = getfield(g,"components") + local c = g.components if c then -- it happens that we copied a ligature free_nodelist(c) - setfield(g,"components",nil) - setfield(g,"subtype",256) + g.components = nil + g.subtype = 256 end - local a = getattr(n,a_characters) - -- local s = copy_node(getfield(n,"spec")) - -- this will be fixed in luatex but for now a temp hack (zero test) - local s = getfield(n,"spec") - s = s == 0 and new_gluespec(0) or copy_node(s) - -- - setfield(g,"char",32) - setfield(n,"spec",s) - -- insert_after(p,p,g) - setfield(p,"next",g) - setfield(g,"prev",p) - setfield(g,"next",n) - setfield(n,"prev",g) - setfield(s,"width",getfield(s,"width") - getfield(g,"width")) + local a = n[a_characters] + local s = copy_node(n.spec) + g.char, n.spec = 32, s + p.next, g.prev = g, p + g.next, n.prev = n, g + s.width = s.width - g.width if a then - setattr(g,a_characters,a) + g[a_characters] = a end - setattr(s,a_characters,0) - setattr(n,a_characters,0) + s[a_characters] = 0 + n[a_characters] = 0 end -- end elseif id == hlist_code or id == vlist_code then - injectspaces(getlist(n),attribute) + injectspaces(n.list,attribute) -- elseif id == kern_code then -- the backend already collapses -- local first = n -- while true do - -- local nn = getnext(n) - -- if nn and getid(nn) == kern_code then + -- local nn = n.next + -- if nn and nn.id == kern_code then -- -- maybe we should delete kerns but who cares at this stage - -- setfield(first,"kern",getfield(first,"kern") + getfield(nn,"kern") - -- setfield(nn,"kern",0) + -- first.kern = first.kern + nn.kern + -- nn.kern = 0 -- n = nn -- else -- break -- end -- end end - p_id = id p = n - n = getnext(n) + n = n.next end - return head, true -- always done anyway + return head, true end -nodes.handlers.accessibility = function(head) - local head, done = injectspaces(tonut(head)) - return tonode(head), done -end +nodes.handlers.accessibility = injectspaces -- todo: @@ -122,18 +90,16 @@ end -- local function compact(n) -- local t = { } -- for n in traverse_id(glyph_code,n) do --- t[#t+1] = utfchar(getchar(n)) -- check for unicode +-- t[#t+1] = utfchar(n.char) -- check for unicode -- end -- return concat(t,"") -- end -- -- local function injectspans(head) --- local done = false --- for n in traverse_nodes(tonuts(head)) do --- local id = getid(n) +-- for n in traverse_nodes(head) do +-- local id = n.id -- if id == disc then --- local r = getfield(n,"replace") --- local p = getfield(n,"pre") +-- local r, p = n.replace, n.pre -- if r and p then -- local str = compact(r) -- local hsh = hyphenated[str] @@ -142,14 +108,13 @@ end -- hyphenated[str] = hsh -- codes[hsh] = str -- end --- setattr(n,a_hyphenated,hsh) --- done = true +-- n[a_hyphenated] = hsh -- end -- elseif id == hlist_code or id == vlist_code then --- injectspans(getlist(n)) +-- injectspans(n.list) -- end -- end --- return tonodes(head), done +-- return head, true -- end -- -- nodes.injectspans = injectspans @@ -157,22 +122,19 @@ end -- tasks.appendaction("processors", "words", "nodes.injectspans") -- -- local function injectspans(head) --- local done = false --- for n in traverse_nodes(tonut(head)) do --- local id = getid(n) +-- for n in traverse_nodes(head) do +-- local id = n.id -- if id == disc then --- local a = getattr(n,a_hyphenated) +-- local a = n[a_hyphenated] -- if a then -- local str = codes[a] -- local b = new_pdfliteral(format("/Span << /ActualText %s >> BDC", lpdf.tosixteen(str))) -- local e = new_pdfliteral("EMC") --- insert_before(head,n,b) --- insert_after(head,n,e) --- done = true +-- node.insert_before(head,n,b) +-- node.insert_after(head,n,e) -- end -- elseif id == hlist_code or id == vlist_code then --- injectspans(getlist(n)) +-- injectspans(n.list) -- end -- end --- return tonodes(head), done -- end diff --git a/tex/context/base/node-aux.lua b/tex/context/base/node-aux.lua index 7f4b0342a..443c78547 100644 --- a/tex/context/base/node-aux.lua +++ b/tex/context/base/node-aux.lua @@ -22,108 +22,82 @@ local vlist_code = nodecodes.vlist local attributelist_code = nodecodes.attributelist -- temporary local math_code = nodecodes.math -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode -local vianuts = nuts.vianuts - -local getbox = nuts.getbox -local getnext = nuts.getnext -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getfont = nuts.getfont -local getchar = nuts.getchar -local getattr = nuts.getattr -local setfield = nuts.setfield -local setattr = nuts.setattr - -local traverse_nodes = nuts.traverse -local traverse_id = nuts.traverse_id -local free_node = nuts.free -local hpack_nodes = nuts.hpack -local unset_attribute = nuts.unset_attribute -local first_glyph = nuts.first_glyph -local copy_node = nuts.copy -local copy_node_list = nuts.copy_list -local find_tail = nuts.tail -local insert_node_after = nuts.insert_after -local isnode = nuts.is_node - -local nodes_traverse_id = nodes.traverse_id -local nodes_first_glyph = nodes.first_glyph - -local nodepool = nuts.pool +local nodepool = nodes.pool + local new_glue = nodepool.glue local new_glyph = nodepool.glyph +local traverse_nodes = node.traverse +local traverse_id = node.traverse_id +local free_node = node.free +local hpack_nodes = node.hpack +local unset_attribute = node.unset_attribute +local first_glyph = node.first_glyph or node.first_character +local copy_node = node.copy +local copy_node_list = node.copy_list +local slide_nodes = node.slide +local insert_node_after = node.insert_after +local isnode = node.is_node + local unsetvalue = attributes.unsetvalue local current_font = font.current +local texgetbox = tex.getbox + local report_error = logs.reporter("node-aux:error") -local function repackhlist(list,...) +function nodes.repackhlist(list,...) +--~ nodes.showsimplelist(list) local temp, b = hpack_nodes(list,...) - list = getlist(temp) - setfield(temp,"list",nil) + list = temp.list + temp.list = nil free_node(temp) return list, b end -nuts.repackhlist = repackhlist - -function nodes.repackhlist(list,...) - local list, b = repackhlist(tonut(list),...) - return tonode(list), b -end - local function set_attributes(head,attr,value) for n in traverse_nodes(head) do - setattr(n,attr,value) - local id = getid(n) + n[attr] = value + local id = n.id if id == hlist_node or id == vlist_node then - set_attributes(getlist(n),attr,value) + set_attributes(n.list,attr,value) end end end local function set_unset_attributes(head,attr,value) for n in traverse_nodes(head) do - if not getattr(n,attr) then - setattr(n,attr,value) + if not n[attr] then + n[attr] = value end - local id = getid(n) + local id = n.id if id == hlist_code or id == vlist_code then - set_unset_attributes(getlist(n),attr,value) + set_unset_attributes(n.list,attr,value) end end end local function unset_attributes(head,attr) for n in traverse_nodes(head) do - setattr(n,attr,unsetvalue) - local id = getid(n) + n[attr] = unsetvalue + local id = n.id if id == hlist_code or id == vlist_code then - unset_attributes(getlist(n),attr) + unset_attributes(n.list,attr) end end end --- for old times sake +nodes.setattribute = node.set_attribute +nodes.getattribute = node.has_attribute +nodes.unsetattribute = node.unset_attribute +nodes.has_attribute = node.has_attribute -nuts.setattribute = nuts.setattr nodes.setattribute = nodes.setattr -nuts.getattribute = nuts.getattr nodes.getattribute = nodes.getattr -nuts.unsetattribute = nuts.unset_attribute nodes.unsetattribute = nodes.unset_attribute -nuts.has_attribute = nuts.has_attribute nodes.has_attribute = nodes.has_attribute -nuts.firstglyph = nuts.first_glyph nodes.firstglyph = nodes.first_glyph +nodes.firstglyph = first_glyph +nodes.setattributes = set_attributes +nodes.setunsetattributes = set_unset_attributes +nodes.unsetattributes = unset_attributes -nuts.setattributes = set_attributes nodes.setattributes = vianuts(set_attributes) -nuts.setunsetattributes = set_unset_attributes nodes.setunsetattributes = vianuts(set_unset_attributes) -nuts.unsetattributes = unset_attributes nodes.unsetattributes = vianuts(unset_attributes) - --- history: --- -- function nodes.is_skipable(a,id) -- skipable nodes at the margins during character protrusion -- return ( -- id ~= glyph_node @@ -132,26 +106,29 @@ nuts.unsetattributes = unset_attributes nodes.unsetattribut -- or id == adjust_node -- or id == penalty_node -- or (id == glue_node and a.spec.writable) --- or (id == disc_node and getfield(a,"pre") == nil and getfield(a,"post") == nil and getfield(a,"replace") == nil) --- or (id == math_node and getfield(a,"surround") == 0) --- or (id == kern_node and (getfield(a,"kern") == 0 or getsubtype(subtype) == NORMAL)) --- or (id == hlist_node and getfield(a,"width") == 0 and getfield(a,"height") == 0 and getfield(a,"depth") == 0 and getlist(a) == nil) --- or (id == whatsit_node and getsubtype(a) ~= pdf_refximage_node and getsubtype(a) ~= pdf_refxform_node) +-- or (id == disc_node and a.pre == nil and a.post == nil and a.replace == nil) +-- or (id == math_node and a.surround == 0) +-- or (id == kern_node and (a.kern == 0 or a.subtype == NORMAL)) +-- or (id == hlist_node and a.width == 0 and a.height == 0 and a.depth == 0 and a.list == nil) +-- or (id == whatsit_node and a.subtype ~= pdf_refximage_node and a.subtype ~= pdf_refxform_node) -- ) -- end + +-- history: +-- -- -- local function glyph_width(a) --- local ch = chardata[getfont(a)][getchar(a)] +-- local ch = chardata[a.font][a.char] -- return (ch and ch.width) or 0 -- end -- -- local function glyph_total(a) --- local ch = chardata[getfont(a)][getchar(a)] +-- local ch = chardata[a.font][a.char] -- return (ch and (ch.height+ch.depth)) or 0 -- end -- -- local function non_discardable(a) -- inline --- return getid(id) < math_node -- brrrr +-- return a.id < math_node -- brrrr -- end -- -- local function calculate_badness(t,s) @@ -206,36 +183,8 @@ nuts.unsetattributes = unset_attributes nodes.unsetattribut -- return -u -- end -- end --- --- if not node.end_of_math then --- function node.end_of_math(n) --- for n in traverse_id(math_code,getnext(next)) do --- return n --- end --- end --- end --- --- nodes.endofmath = node.end_of_math --- --- local function firstline(n) --- while n do --- local id = getid(n) --- if id == hlist_code then --- if getsubtype(n) == line_code then --- return n --- else --- return firstline(getlist(n)) --- end --- elseif id == vlist_code then --- return firstline(getlist(n)) --- end --- n = getnext(n) --- end --- end --- --- nodes.firstline = firstline -function nuts.firstcharacter(n,untagged) -- tagged == subtype > 255 +function nodes.firstcharacter(n,untagged) -- tagged == subtype > 255 if untagged then return first_glyph(n) else @@ -245,38 +194,44 @@ function nuts.firstcharacter(n,untagged) -- tagged == subtype > 255 end end --- function nodes.firstcharacter(n,untagged) -- tagged == subtype > 255 --- if untagged then --- return nodes_first_glyph(n) --- else --- for g in nodes_traverse_id(glyph_code,n) do --- return g --- end --- end --- end - -local function firstcharinbox(n) - local l = getlist(getbox(n)) +function nodes.firstcharinbox(n) + local l = texgetbox(n).list if l then for g in traverse_id(glyph_code,l) do - return getchar(g) + return g.char end end return 0 end -nuts .firstcharinbox = firstcharinbox -nodes.firstcharinbox = firstcharinbox -nodes.firstcharacter = vianuts(firstcharacter) - -function commands.buildtextaccent(n) - local char = firstcharinbox(n) - if char > 0 then - -- context.accent(false,char) - context([[\accent%s\relax]],char) +if not node.end_of_math then + function node.end_of_math(n) + for n in traverse_id(math_code,n.next) do + return n + end end end +nodes.endofmath = node.end_of_math + +-- local function firstline(n) +-- while n do +-- local id = n.id +-- if id == hlist_code then +-- if n.subtype == line_code then +-- return n +-- else +-- return firstline(n.list) +-- end +-- elseif id == vlist_code then +-- return firstline(n.list) +-- end +-- n = n.next +-- end +-- end + +-- nodes.firstline = firstline + -- this depends on fonts, so we have a funny dependency ... will be -- sorted out .. we could make tonodes a plugin into this @@ -287,8 +242,10 @@ local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob- local head, tail, space, fnt, template = nil, nil, nil, nil, nil if not fnt then fnt = current_font() - elseif type(fnt) ~= "number" and getid(fnt) == glyph_code then -- so it has to be a real node - fnt, template = nil, tonut(fnt) + elseif type(fnt) ~= "number" and fnt.id == "glyph" then + fnt, template = nil, fnt + -- else + -- already a number end for s in utfvalues(str) do local n @@ -302,12 +259,12 @@ local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob- end elseif template then n = copy_node(template) - setvalue(n,"char",s) + n.char = s else n = new_glyph(fnt,s) end if attr then -- normally false when template - setfield(n,"attr",copy_node_list(attr)) + n.attr = copy_node_list(attr) end if head then insert_node_after(head,tail,n) @@ -319,130 +276,69 @@ local function tonodes(str,fnt,attr) -- (str,template_glyph) -- moved from blob- return head, tail end -nuts.tonodes = tonodes +nodes.tonodes = tonodes -nodes.tonodes = function(str,fnt,attr) - local head, tail = tonodes(str,fnt,attr) - return tonode(head), tonode(tail) -end - --- local function link(list,currentfont,currentattr,head,tail) --- for i=1,#list do --- local n = list[i] --- if n then --- local tn = isnode(n) --- if not tn then --- local tn = type(n) --- if tn == "number" then --- if not currentfont then --- currentfont = current_font() --- end --- local h, t = tonodes(tostring(n),currentfont,currentattr) --- if not h then --- -- skip --- elseif not head then --- head = h --- tail = t --- else --- setfield(tail,"next",h) --- setfield(h,"prev",t) --- tail = t --- end --- elseif tn == "string" then --- if #tn > 0 then --- if not currentfont then --- currentfont = current_font() --- end --- local h, t = tonodes(n,currentfont,currentattr) --- if not h then --- -- skip --- elseif not head then --- head, tail = h, t --- else --- setfield(tail,"next",h) --- setfield(h,"prev",t) --- tail = t --- end --- end --- elseif tn == "table" then --- if #tn > 0 then --- if not currentfont then --- currentfont = current_font() --- end --- head, tail = link(n,currentfont,currentattr,head,tail) --- end --- end --- elseif not head then --- head = n --- tail = find_tail(n) --- elseif getid(n) == attributelist_code then --- -- weird case --- report_error("weird node type in list at index %s:",i) --- for i=1,#list do --- local l = list[i] --- report_error("%3i: %s %S",i,getid(l) == attributelist_code and "!" or ">",l) --- end --- os.exit() --- else --- setfield(tail,"next",n) --- setfield(n,"prev",tail) --- if getnext(n) then --- tail = find_tail(n) --- else --- tail = n --- end --- end --- else --- -- permitting nil is convenient --- end --- end --- return head, tail --- end - -local function link(list,currentfont,currentattr,head,tail) -- an oldie, might be replaced +local function link(list,currentfont,currentattr,head,tail) for i=1,#list do local n = list[i] if n then - local tn = type(n) - if tn == "string" then - if #tn > 0 then + local tn = isnode(n) + if not tn then + local tn = type(n) + if tn == "number" then if not currentfont then currentfont = current_font() end - local h, t = tonodes(n,currentfont,currentattr) + local h, t = tonodes(tostring(n),currentfont,currentattr) if not h then -- skip elseif not head then head, tail = h, t else - setfield(tail,"next",h) - setfield(h,"prev",t) - tail = t + tail.next, h.prev, tail = h, t, t end - end - elseif tn == "table" then - if #tn > 0 then - if not currentfont then - currentfont = current_font() + elseif tn == "string" then + if #tn > 0 then + if not currentfont then + currentfont = current_font() + end + local h, t = tonodes(n,currentfont,currentattr) + if not h then + -- skip + elseif not head then + head, tail = h, t + else + tail.next, h.prev, tail = h, t, t + end + end + elseif tn == "table" then + if #tn > 0 then + if not currentfont then + currentfont = current_font() + end + head, tail = link(n,currentfont,currentattr,head,tail) end - head, tail = link(n,currentfont,currentattr,head,tail) end elseif not head then head = n - tail = find_tail(n) - elseif getid(n) == attributelist_code then + if n.next then + tail = slide_nodes(n) + else + tail = n + end + elseif n.id == attributelist_code then -- weird case report_error("weird node type in list at index %s:",i) for i=1,#list do local l = list[i] - report_error("%3i: %s %S",i,getid(l) == attributelist_code and "!" or ">",l) + report_error("%3i: %s %S",i,l.id == attributelist_code and "!" or ">",l) end os.exit() else - setfield(tail,"next",n) - setfield(n,"prev",tail) - if getnext(n) then - tail = find_tail(n) + tail.next = n + n.prev = tail + if n.next then + tail = slide_nodes(n) else tail = n end @@ -454,22 +350,17 @@ local function link(list,currentfont,currentattr,head,tail) -- an oldie, might b return head, tail end -nuts.link = link - -nodes.link = function(list,currentfont,currentattr,head,tail) - local head, tail = link(list,currentfont,currentattr,tonut(head),tonut(tail)) - return tonode(head), tonode(tail) -end +nodes.link = link local function locate(start,wantedid,wantedsubtype) for n in traverse_nodes(start) do - local id = getid(n) + local id = n.id if id == wantedid then - if not wantedsubtype or getsubtype(n) == wantedsubtype then + if not wantedsubtype or n.subtype == wantedsubtype then return n end elseif id == hlist_code or id == vlist_code then - local found = locate(getlist(n),wantedid,wantedsubtype) + local found = locate(n.list,wantedid,wantedsubtype) if found then return found end @@ -477,12 +368,7 @@ local function locate(start,wantedid,wantedsubtype) end end -nuts.locate = locate - -nodes.locate = function(start,wantedid,wantedsubtype) - local found = locate(tonut(start),wantedid,wantedsubtype) - return found and tonode(found) -end +nodes.locate = locate -- I have no use for this yet: -- @@ -495,12 +381,10 @@ end -- return (badness/100)^(1/3) -- end -- --- function tex.stretch_amount(skip,badness) -- node no nut +-- function tex.stretch_amount(skip,badness) -- if skip.id == gluespec_code then -- return skip.width + (badness and (badness/100)^(1/3) or 1) * skip.stretch -- else -- return 0 -- end -- end - - diff --git a/tex/context/base/node-bck.lua b/tex/context/base/node-bck.lua index 4b7b4a064..feaa2c684 100644 --- a/tex/context/base/node-bck.lua +++ b/tex/context/base/node-bck.lua @@ -11,8 +11,6 @@ if not modules then modules = { } end modules ['node-bck'] = { local attributes, nodes, node = attributes, nodes, node -local tasks = nodes.tasks - local nodecodes = nodes.nodecodes local listcodes = nodes.listcodes @@ -21,25 +19,11 @@ local vlist_code = nodecodes.vlist local glyph_code = nodecodes.glyph local cell_code = listcodes.cell -local nuts = nodes.nuts -local nodepool = nuts.pool - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr -local setattr = nuts.setattr -local getsubtype = nuts.getsubtype - -local traverse = nuts.traverse -local traverse_id = nuts.traverse_id +local traverse = node.traverse +local traverse_id = node.traverse_id +local nodepool = nodes.pool +local tasks = nodes.tasks local new_rule = nodepool.rule local new_glue = nodepool.glue @@ -53,50 +37,50 @@ local a_alignbackground = attributes.private('alignbackground') local function add_backgrounds(head) -- rather old code .. to be redone local current = head while current do - local id = getid(current) + local id = current.id if id == hlist_code or id == vlist_code then - local list = getlist(current) + local list = current.list if list then local head = add_backgrounds(list) if head then - setfield(current,"list",head) + current.list = head list = head end end - local width = getfield(current,"width") + local width = current.width if width > 0 then - local background = getattr(current,a_background) + local background = current[a_background] if background then -- direct to hbox -- colorspace is already set so we can omit that and stick to color - local mode = getattr(current,a_colorspace) + local mode = current[a_colorspace] if mode then - local height = getfield(current,"height") - local depth = getfield(current,"depth") + local height = current.height + local depth = current.depth local skip = id == hlist_code and width or (height + depth) local glue = new_glue(-skip) local rule = new_rule(width,height,depth) - local color = getattr(current,a_color) - local transparency = getattr(current,a_transparency) - setattr(rule,a_colorspace,mode) + local color = current[a_color] + local transparency = current[a_transparency] + rule[a_colorspace] = mode if color then - setattr(rule,a_color,color) + rule[a_color] = color end if transparency then - setattr(rule,a_transparency,transparency) + rule[a_transparency] = transparency end - setfield(rule,"next",glue) - setfield(glue,"prev",rule) + rule.next = glue + glue.prev = rule if list then - setfield(glue,"next",list) - setfield(list,"prev",glue) + glue.next = list + list.prev = glue end - setfield(current,"list",rule) + current.list = rule end end end end - current = getnext(current) + current = current.next end return head, true end @@ -104,16 +88,16 @@ end local function add_alignbackgrounds(head) local current = head while current do - local id = getid(current) + local id = current.id if id == hlist_code then - local list = getlist(current) + local list = current.list if not list then -- no need to look - elseif getsubtype(current) == cell_code then + elseif current.subtype == cell_code then local background = nil local found = nil -- for l in traverse(list) do - -- background = getattr(l,a_alignbackground) + -- background = l[a_alignbackground] -- if background then -- found = l -- break @@ -122,7 +106,7 @@ local function add_alignbackgrounds(head) -- we know that it's a fake hlist (could be user node) -- but we cannot store tables in user nodes yet for l in traverse_id(hpack_code,list) do - background = getattr(l,a_alignbackground) + background = l[a_alignbackground] if background then found = l end @@ -131,28 +115,28 @@ local function add_alignbackgrounds(head) -- if background then -- current has subtype 5 (cell) - local width = getfield(current,"width") + local width = current.width if width > 0 then - local mode = getattr(found,a_colorspace) + local mode = found[a_colorspace] if mode then local glue = new_glue(-width) - local rule = new_rule(width,getfield(current,"height"),getfield(current,"depth")) - local color = getattr(found,a_color) - local transparency = getattr(found,a_transparency) - setattr(rule,a_colorspace,mode) + local rule = new_rule(width,current.height,current.depth) + local color = found[a_color] + local transparency = found[a_transparency] + rule[a_colorspace] = mode if color then - setattr(rule,a_color,color) + rule[a_color] = color end if transparency then - setattr(rule,a_transparency,transparency) + rule[a_transparency] = transparency end - setfield(rule,"next",glue) - setfield(glue,"prev",rule) + rule.next = glue + glue.prev = rule if list then - setfield(glue,"next",list) - setfield(list,"prev",glue) + glue.next = list + list.prev = glue end - setfield(current,"list",rule) + current.list = rule end end end @@ -160,23 +144,18 @@ local function add_alignbackgrounds(head) add_alignbackgrounds(list) end elseif id == vlist_code then - local list = getlist(current) + local list = current.list if list then add_alignbackgrounds(list) end end - current = getnext(current) + current = current.next end return head, true end --- nodes.handlers.backgrounds = add_backgrounds --- nodes.handlers.alignbackgrounds = add_alignbackgrounds - -nodes.handlers.backgrounds = function(head) local head, done = add_backgrounds (tonut(head)) return tonode(head), done end -nodes.handlers.alignbackgrounds = function(head) local head, done = add_alignbackgrounds(tonut(head)) return tonode(head), done end - --- elsewhere: needs checking +nodes.handlers.backgrounds = add_backgrounds +nodes.handlers.alignbackgrounds = add_alignbackgrounds tasks.appendaction("shipouts","normalizers","nodes.handlers.backgrounds") tasks.appendaction("shipouts","normalizers","nodes.handlers.alignbackgrounds") diff --git a/tex/context/base/node-fin.lua b/tex/context/base/node-fin.lua index 8476b47a6..63a5ef83e 100644 --- a/tex/context/base/node-fin.lua +++ b/tex/context/base/node-fin.lua @@ -8,54 +8,36 @@ if not modules then modules = { } end modules ['node-fin'] = { -- this module is being reconstructed -- local functions, only slightly slower --- --- leaders are also triggers local next, type, format = next, type, string.format local attributes, nodes, node = attributes, nodes, node -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getleader = nuts.getleader -local getattr = nuts.getattr - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local copy_node = nuts.copy -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after +local copy_node = node.copy +local find_tail = node.slide -local nodecodes = nodes.nodecodes -local whatcodes = nodes.whatcodes +local nodecodes = nodes.nodecodes +local whatcodes = nodes.whatcodes -local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local glue_code = nodecodes.glue -local rule_code = nodecodes.rule -local whatsit_code = nodecodes.whatsit -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local glue_code = nodecodes.glue +local rule_code = nodecodes.rule +local whatsit_code = nodecodes.whatsit +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist -local pdfliteral_code = whatcodes.pdfliteral +local pdfliteral_code = whatcodes.pdfliteral -local states = attributes.states -local numbers = attributes.numbers -local a_trigger = attributes.private('trigger') -local triggering = false +local states = attributes.states +local numbers = attributes.numbers +local a_trigger = attributes.private('trigger') +local triggering = false -local starttiming = statistics.starttiming -local stoptiming = statistics.stoptiming -local loadstripped = utilities.lua.loadstripped -local unsetvalue = attributes.unsetvalue +local starttiming = statistics.starttiming +local stoptiming = statistics.stoptiming +local loadstripped = utilities.lua.loadstripped +local unsetvalue = attributes.unsetvalue -- these two will be like trackers @@ -120,14 +102,11 @@ function nodes.installattributehandler(plugin) return loadstripped(template)() end --- for the moment: - -local function copied(n) - return copy_node(tonut(n)) -end - -- the injectors +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after + local nsdata, nsnone, nslistwise, nsforced, nsselector, nstrigger local current, current_selector, done = 0, 0, false -- nb, stack has a local current ! local nsbegin, nsend @@ -153,25 +132,23 @@ end function states.finalize(namespace,attribute,head) -- is this one ok? if current > 0 and nsnone then - head = tonut(head) - local id = getid(head) + local id = head.id if id == hlist_code or id == vlist_code then - local list = getlist(head) + local list = head.list if list then - list = insert_node_before(list,list,copied(nsnone)) -- two return values - setfield(head,"list",list) + head.list = insert_node_before(list,list,copy_node(nsnone)) end else - head = insert_node_before(head,head,copied(nsnone)) + head = insert_node_before(head,head,copy_node(nsnone)) end - return tonode(head), true, true + return head, true, true end return head, false, false end -- disc nodes can be ignored -- we need to deal with literals too (reset as well as oval) --- if id == glyph_code or (id == whatsit_code and getsubtype(stack) == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then +-- if id == glyph_code or (id == whatsit_code and stack.subtype == pdfliteral_code) or (id == rule_code and stack.width ~= 0) or (id == glue_code and stack.leader) then local function process(namespace,attribute,head,inheritance,default) -- one attribute local stack = head @@ -179,57 +156,53 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr local check = false local leader = nil while stack do - local id = getid(stack) + local id = stack.id if id == glyph_code then check = true elseif id == glue_code then - leader = getleader(stack) + leader = stack.leader if leader then check = true end elseif id == hlist_code or id == vlist_code then - local content = getlist(stack) + local content = stack.list if content then -- begin nested -- - if nstrigger and getattr(stack,nstrigger) then - local outer = getattr(stack,attribute) + local ok + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] if outer ~= inheritance then - local list, ok = process(namespace,attribute,content,inheritance,outer) - setfield(stack,"list",list) - done = done or ok + stack.list, ok = process(namespace,attribute,content,inheritance,outer) else - local list, ok = process(namespace,attribute,content,inheritance,default) - setfield(stack,"list",list) - done = done or ok + stack.list, ok = process(namespace,attribute,content,inheritance,default) end else - local list, ok = process(namespace,attribute,content,inheritance,default) - setfield(stack,"list",list) - done = done or ok + stack.list, ok = process(namespace,attribute,content,inheritance,default) end -- end nested -- + done = done or ok end elseif id == rule_code then - check = getfield(stack,"width") ~= 0 + check = stack.width ~= 0 end -- much faster this way than using a check() and nested() function if check then - local c = getattr(stack,attribute) + local c = stack[attribute] if c then if default and c == inheritance then if current ~= default then - head = insert_node_before(head,stack,copied(nsdata[default])) + head = insert_node_before(head,stack,copy_node(nsdata[default])) current = default done = true end elseif current ~= c then - head = insert_node_before(head,stack,copied(nsdata[c])) + head = insert_node_before(head,stack,copy_node(nsdata[c])) current = c done = true end if leader then local savedcurrent = current - local ci = getid(leader) + local ci = leader.id if ci == hlist_code or ci == vlist_code then -- else we reset inside a box unneeded, okay, the downside is -- that we trigger color in each repeated box, so there is room @@ -237,48 +210,41 @@ local function process(namespace,attribute,head,inheritance,default) -- one attr current = 0 end -- begin nested -- - if nstrigger and getattr(stack,nstrigger) then - local outer = getattr(stack,attribute) + local ok = false + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] if outer ~= inheritance then - local list, ok = process(namespace,attribute,leader,inheritance,outer) - setfield(stack,"leader",list) - done = done or ok + stack.leader, ok = process(namespace,attribute,leader,inheritance,outer) else - local list, ok = process(namespace,attribute,leader,inheritance,default) - setfield(stack,"leader",list) - done = done or ok + stack.leader, ok = process(namespace,attribute,leader,inheritance,default) end else - local list, ok = process(namespace,attribute,leader,inheritance,default) - setfield(stack,"leader",list) - done = done or ok + stack.leader, ok = process(namespace,attribute,leader,inheritance,default) end -- end nested -- + done = done or ok current = savedcurrent leader = false end elseif default and inheritance then if current ~= default then - head = insert_node_before(head,stack,copied(nsdata[default])) + head = insert_node_before(head,stack,copy_node(nsdata[default])) current = default done = true end elseif current > 0 then - head = insert_node_before(head,stack,copied(nsnone)) + head = insert_node_before(head,stack,copy_node(nsnone)) current = 0 done = true end check = false end - stack = getnext(stack) + stack = stack.next end return head, done end -states.process = function(namespace,attribute,head,default) - local head, done = process(namespace,attribute,tonut(head),default) - return tonode(head), done -end +states.process = process -- we can force a selector, e.g. document wide color spaces, saves a little -- watch out, we need to check both the selector state (like colorspace) and @@ -292,103 +258,93 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at local check = false local leader = nil while stack do - local id = getid(stack) + local id = stack.id if id == glyph_code then check = true elseif id == glue_code then - leader = getleader(stack) + leader = stack.leader if leader then check = true end elseif id == hlist_code or id == vlist_code then - local content = getlist(stack) + local content = stack.list if content then + local ok = false -- begin nested - if nstrigger and getattr(stack,nstrigger) then - local outer = getattr(stack,attribute) + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] if outer ~= inheritance then - local list, ok = selective(namespace,attribute,content,inheritance,outer) - setfield(stack,"list",list) - done = done or ok + stack.list, ok = selective(namespace,attribute,content,inheritance,outer) else - local list, ok = selective(namespace,attribute,content,inheritance,default) - setfield(stack,"list",list) - done = done or ok + stack.list, ok = selective(namespace,attribute,content,inheritance,default) end else - local list, ok = selective(namespace,attribute,content,inheritance,default) - setfield(stack,"list",list) - done = done or ok + stack.list, ok = selective(namespace,attribute,content,inheritance,default) end -- end nested + done = done or ok end elseif id == rule_code then - check = getfield(stack,"width") ~= 0 + check = stack.width ~= 0 end if check then - local c = getattr(stack,attribute) + local c = stack[attribute] if c then if default and c == inheritance then if current ~= default then local data = nsdata[default] - head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector])) + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) current = default done = true end else - local s = getattr(stack,nsselector) + local s = stack[nsselector] if current ~= c or current_selector ~= s then local data = nsdata[c] - head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector])) + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) current = c current_selector = s done = true end end if leader then + local ok = false -- begin nested - if nstrigger and getattr(stack,nstrigger) then - local outer = getatribute(stack,attribute) + if nstrigger and stack[nstrigger] then + local outer = stack[attribute] if outer ~= inheritance then - local list, ok = selective(namespace,attribute,leader,inheritance,outer) - setfield(stack,"leader",list) - done = done or ok + stack.leader, ok = selective(namespace,attribute,leader,inheritance,outer) else - local list, ok = selective(namespace,attribute,leader,inheritance,default) - setfield(stack,"leader",list) - done = done or ok + stack.leader, ok = selective(namespace,attribute,leader,inheritance,default) end else - local list, ok = selective(namespace,attribute,leader,inheritance,default) - setfield(stack,"leader",list) - done = done or ok + stack.leader, ok = selective(namespace,attribute,leader,inheritance,default) end -- end nested - leader = false + done = done or ok + leader = false end elseif default and inheritance then if current ~= default then local data = nsdata[default] - head = insert_node_before(head,stack,copied(data[nsforced or getattr(stack,nsselector) or nsselector])) + head = insert_node_before(head,stack,copy_node(data[nsforced or stack[nsselector] or nsselector])) current = default done = true end elseif current > 0 then - head = insert_node_before(head,stack,copied(nsnone)) + head = insert_node_before(head,stack,copy_node(nsnone)) current, current_selector, done = 0, 0, true end check = false end - stack = getnext(stack) + + stack = stack.next end return head, done end -states.selective = function(namespace,attribute,head,default) - local head, done = selective(namespace,attribute,tonut(head),default) - return tonode(head), done -end +states.selective = selective -- Ideally the next one should be merged with the previous but keeping it separate is -- safer. We deal with two situations: efficient boxwise (layoutareas) and mixed layers @@ -407,80 +363,76 @@ local function stacked(namespace,attribute,head,default) -- no triggering, no in local check = false local leader = false while stack do - local id = getid(stack) + local id = stack.id if id == glyph_code then check = true elseif id == glue_code then - leader = getleader(stack) + leader = stack.leader if leader then check = true end elseif id == hlist_code or id == vlist_code then - local content = getlist(stack) + local content = stack.list if content then -- the problem is that broken lines gets the attribute which can be a later one if nslistwise then - local a = getattr(stack,attribute) + local a = stack[attribute] if a and current ~= a and nslistwise[a] then -- viewerlayer / needs checking, see below local p = current - current = a - head = insert_node_before(head,stack,copied(nsdata[a])) - local list = stacked(namespace,attribute,content,current) -- two return values - setfield(stack,"list",list) - done = true - head, stack = insert_node_after(head,stack,copied(nsnone)) + current, done = a, true + head = insert_node_before(head,stack,copy_node(nsdata[a])) + stack.list = stacked(namespace,attribute,content,current) + head, stack = insert_node_after(head,stack,copy_node(nsnone)) current = p else - local list, ok = stacked(namespace,attribute,content,current) - setfield(stack,"list",list) -- only if ok + local ok = false + stack.list, ok = stacked(namespace,attribute,content,current) done = done or ok end else - local list, ok = stacked(namespace,attribute,content,current) - setfield(stack,"list",list) -- only if ok + local ok = false + stack.list, ok = stacked(namespace,attribute,content,current) done = done or ok end end elseif id == rule_code then - check = getfield(stack,"width") ~= 0 + check = stack.width ~= 0 end if check then - local a = getattr(stack,attribute) + local a = stack[attribute] if a then if current ~= a then - head = insert_node_before(head,stack,copied(nsdata[a])) + head = insert_node_before(head,stack,copy_node(nsdata[a])) depth = depth + 1 current, done = a, true end if leader then - local list, ok = stacked(namespace,attribute,content,current) - setfield(stack,"leader",list) -- only if ok + local ok = false + stack.leader, ok = stacked(namespace,attribute,content,current) done = done or ok leader = false end elseif default > 0 then -- elseif current > 0 then - head = insert_node_before(head,stack,copied(nsnone)) + head = insert_node_before(head,stack,copy_node(nsnone)) depth = depth - 1 current, done = 0, true end check = false end - stack = getnext(stack) + + stack = stack.next end while depth > 0 do - head = insert_node_after(head,stack,copied(nsnone)) + head = insert_node_after(head,stack,copy_node(nsnone)) depth = depth - 1 end return head, done end -states.stacked = function(namespace,attribute,head,default) - local head, done = stacked(namespace,attribute,tonut(head),default) - return tonode(head), done -end +states.stacked = stacked -- experimental @@ -494,53 +446,52 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in local check = false local leader = false while current do - local id = getid(current) + local id = current.id if id == glyph_code then check = true elseif id == glue_code then - leader = getleader(current) + leader = current.leader if leader then check = true end elseif id == hlist_code or id == vlist_code then - local content = getlist(current) + local content = current.list if not content then -- skip elseif nslistwise then - local a = getattr(current,attribute) + local a = current[attribute] if a and attrib ~= a and nslistwise[a] then -- viewerlayer - head = insert_node_before(head,current,copied(nsdata[a])) - local list = stacker(namespace,attribute,content,a) - setfield(current,"list",list) done = true - head, current = insert_node_after(head,current,copied(nsnone)) + head = insert_node_before(head,current,copy_node(nsdata[a])) + current.list = stacker(namespace,attribute,content,a) + head, current = insert_node_after(head,current,copy_node(nsnone)) else - local list, ok = stacker(namespace,attribute,content,attrib) - setfield(current,"list",list) + local ok = false + current.list, ok = stacker(namespace,attribute,content,attrib) done = done or ok end else - local list, ok = stacker(namespace,attribute,content,default) - setfield(current,"list",list) + local ok = false + current.list, ok = stacker(namespace,attribute,content,default) done = done or ok end elseif id == rule_code then - check = getfield(current,"width") ~= 0 + check = current.width ~= 0 end if check then - local a = getattr(current,attribute) or unsetvalue + local a = current[attribute] or unsetvalue if a ~= attrib then local n = nsstep(a) if n then -- !!!! TEST CODE !!!! - -- head = insert_node_before(head,current,copied(nsdata[tonumber(n)])) -- a - head = insert_node_before(head,current,tonut(n)) -- a + -- head = insert_node_before(head,current,copy_node(nsdata[tonumber(n)])) -- a + head = insert_node_before(head,current,n) -- a end attrib, done, okay = a, true, true if leader then -- tricky as a leader has to be a list so we cannot inject before - local list, ok = stacker(namespace,attribute,leader,attrib) + local _, ok = stacker(namespace,attribute,leader,attrib) done = done or ok leader = false end @@ -549,23 +500,20 @@ local function stacker(namespace,attribute,head,default) -- no triggering, no in end previous = current - current = getnext(current) + current = current.next end if okay then local n = nsend() if n then -- !!!! TEST CODE !!!! - -- head = insert_node_after(head,previous,copied(nsdata[tostring(n)])) - head = insert_node_after(head,previous,tonut(n)) + -- head = insert_node_after(head,previous,copy_node(nsdata[tostring(n)])) + head = insert_node_after(head,previous,n) end end return head, done end -states.stacker = function(namespace,attribute,head,default) - local head, done = stacker(namespace,attribute,tonut(head),default) - return tonode(head), done -end +states.stacker = stacker -- -- -- diff --git a/tex/context/base/node-fnt.lua b/tex/context/base/node-fnt.lua index 7000c4fd7..2f59d513c 100644 --- a/tex/context/base/node-fnt.lua +++ b/tex/context/base/node-fnt.lua @@ -23,24 +23,12 @@ local fontdata = fonthashes.identifiers local otf = fonts.handlers.otf +local traverse_id = node.traverse_id local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming - local nodecodes = nodes.nodecodes local handlers = nodes.handlers -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getattr = nuts.getattr -local getid = nuts.getid -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getnext = nuts.getnext - -local traverse_id = nuts.traverse_id - local glyph_code = nodecodes.glyph local disc_code = nodecodes.disc @@ -121,25 +109,25 @@ function handlers.characters(head) report_fonts() report_fonts("checking node list, run %s",run) report_fonts() - local n = tonut(head) + local n = head while n do - local id = getid(n) + local id = n.id if id == glyph_code then - local font = getfont(n) - local attr = getattr(n,0) or 0 - report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,getchar(n)) + local font = n.font + local attr = n[0] or 0 + report_fonts("font %03i, dynamic %03i, glyph %C",font,attr,n.char) elseif id == disc_code then report_fonts("[disc] %s",nodes.listtoutf(n,true,false,n)) else report_fonts("[%s]",nodecodes[id]) end - n = getnext(n) + n = n.next end end - for n in traverse_id(glyph_code,tonut(head)) do - -- if getsubtype(n) <256 then -- all are 1 - local font = getfont(n) - local attr = getattr(n,0) or 0 -- zero attribute is reserved for fonts in context + for n in traverse_id(glyph_code,head) do + -- if n.subtype<256 then -- all are 1 + local font = n.font + local attr = n[0] or 0 -- zero attribute is reserved for fonts in context if font ~= prevfont or attr ~= prevattr then if attr > 0 then local used = attrfonts[font] @@ -403,8 +391,5 @@ end -- return head, true -- end -local d_protect_glyphs = nuts.protect_glyphs -local d_unprotect_glyphs = nuts.unprotect_glyphs - -handlers.protectglyphs = function(n) return d_protect_glyphs (tonut(n)) end -handlers.unprotectglyphs = function(n) return d_unprotect_glyphs(tonut(n)) end +handlers.protectglyphs = node.protect_glyphs +handlers.unprotectglyphs = node.unprotect_glyphs diff --git a/tex/context/base/node-inj.lua b/tex/context/base/node-inj.lua index f30070e9e..ae48150a6 100644 --- a/tex/context/base/node-inj.lua +++ b/tex/context/base/node-inj.lua @@ -11,7 +11,7 @@ if not modules then modules = { } end modules ['node-inj'] = { -- test fonts. Btw, future versions of luatex will have extended glyph properties -- that can be of help. Some optimizations can go away when we have faster machines. --- todo: ignore kerns between disc and glyph +-- todo: make a special one for context local next = next local utfchar = utf.char @@ -30,32 +30,13 @@ local injections = nodes.injections local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc local kern_code = nodecodes.kern - -local nuts = nodes.nuts -local nodepool = nuts.pool - +local nodepool = nodes.pool local newkern = nodepool.kern -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local traverse_id = nuts.traverse_id -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after +local traverse_id = node.traverse_id +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after local a_kernpair = attributes.private('kernpair') local a_ligacomp = attributes.private('ligacomp') @@ -90,8 +71,8 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne local dx, dy = factor*(exit[1]-entry[1]), factor*(exit[2]-entry[2]) local ws, wn = tfmstart.width, tfmnext.width local bound = #cursives + 1 - setattr(start,a_cursbase,bound) - setattr(nxt,a_curscurs,bound) + start[a_cursbase] = bound + nxt[a_curscurs] = bound cursives[bound] = { rlmode, dx, dy, ws, wn } return dx, dy, bound end @@ -100,14 +81,14 @@ function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr) local x, y, w, h = factor*spec[1], factor*spec[2], factor*spec[3], factor*spec[4] -- dy = y - h if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then - local bound = getattr(current,a_kernpair) + local bound = current[a_kernpair] if bound then local kb = kerns[bound] -- inefficient but singles have less, but weird anyway, needs checking kb[2], kb[3], kb[4], kb[5] = (kb[2] or 0) + x, (kb[3] or 0) + y, (kb[4] or 0)+ w, (kb[5] or 0) + h else bound = #kerns + 1 - setattr(current,a_kernpair,bound) + current[a_kernpair] = bound kerns[bound] = { rlmode, x, y, w, h, r2lflag, tfmchr.width } end return x, y, w, h, bound @@ -119,7 +100,7 @@ function injections.setkern(current,factor,rlmode,x,tfmchr) local dx = factor*x if dx ~= 0 then local bound = #kerns + 1 - setattr(current,a_kernpair,bound) + current[a_kernpair] = bound kerns[bound] = { rlmode, dx } return dx, bound else @@ -129,7 +110,7 @@ end function injections.setmark(start,base,factor,rlmode,ba,ma,index,baseismark) -- ba=baseanchor, ma=markanchor local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2]) -- the index argument is no longer used but when this - local bound = getattr(base,a_markbase) -- fails again we should pass it + local bound = base[a_markbase] -- fails again we should pass it local index = 1 if bound then local mb = marks[bound] @@ -137,19 +118,19 @@ function injections.setmark(start,base,factor,rlmode,ba,ma,index,baseismark) -- -- if not index then index = #mb + 1 end index = #mb + 1 mb[index] = { dx, dy, rlmode } - setattr(start,a_markmark,bound) - setattr(start,a_markdone,index) + start[a_markmark] = bound + start[a_markdone] = index return dx, dy, bound else - report_injections("possible problem, %U is base mark without data (id %a)",getchar(base),bound) + report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound) end end -- index = index or 1 index = index or 1 bound = #marks + 1 - setattr(base,a_markbase,bound) - setattr(start,a_markmark,bound) - setattr(start,a_markdone,index) + base[a_markbase] = bound + start[a_markmark] = bound + start[a_markdone] = index marks[bound] = { [index] = { dx, dy, rlmode, baseismark } } return dx, dy, bound end @@ -161,15 +142,15 @@ end local function trace(head) report_injections("begin run") for n in traverse_id(glyph_code,head) do - if getsubtype(n) < 256 then - local kp = getattr(n,a_kernpair) - local mb = getattr(n,a_markbase) - local mm = getattr(n,a_markmark) - local md = getattr(n,a_markdone) - local cb = getattr(n,a_cursbase) - local cc = getattr(n,a_curscurs) - local char = getchar(n) - report_injections("font %s, char %U, glyph %c",getfont(n),char,char) + if n.subtype < 256 then + local kp = n[a_kernpair] + local mb = n[a_markbase] + local mm = n[a_markmark] + local md = n[a_markdone] + local cb = n[a_cursbase] + local cc = n[a_curscurs] + local char = n.char + report_injections("font %s, char %U, glyph %c",n.font,char,char) if kp then local k = kerns[kp] if k[3] then @@ -217,24 +198,22 @@ local function show_result(head) local current = head local skipping = false while current do - local id = getid(current) + local id = current.id if id == glyph_code then - report_injections("char: %C, width %p, xoffset %p, yoffset %p", - getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset")) + report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset) skipping = false elseif id == kern_code then - report_injections("kern: %p",getfield(current,"kern")) + report_injections("kern: %p",current.kern) skipping = false elseif not skipping then report_injections() skipping = true end - current = getnext(current) + current = current.next end end function injections.handler(head,where,keep) - head = tonut(head) local has_marks, has_cursives, has_kerns = next(marks), next(cursives), next(kerns) if has_marks or has_cursives then if trace_injections then @@ -245,18 +224,17 @@ function injections.handler(head,where,keep) if has_kerns then -- move outside loop local nf, tm = nil, nil for n in traverse_id(glyph_code,head) do -- only needed for relevant fonts - if getsubtype(n) < 256 then + if n.subtype < 256 then nofvalid = nofvalid + 1 valid[nofvalid] = n - local f = getfont(n) - if f ~= nf then - nf = f - tm = fontdata[nf].resources.marks -- other hash in ctx + if n.font ~= nf then + nf = n.font + tm = fontdata[nf].resources.marks end if tm then - mk[n] = tm[getchar(n)] + mk[n] = tm[n.char] end - local k = getattr(n,a_kernpair) + local k = n[a_kernpair] if k then local kk = kerns[k] if kk then @@ -276,16 +254,15 @@ function injections.handler(head,where,keep) else local nf, tm = nil, nil for n in traverse_id(glyph_code,head) do - if getsubtype(n) < 256 then + if n.subtype < 256 then nofvalid = nofvalid + 1 valid[nofvalid] = n - local f = getfont(n) - if f ~= nf then - nf = f - tm = fontdata[nf].resources.marks -- other hash in ctx + if n.font ~= nf then + nf = n.font + tm = fontdata[nf].resources.marks end if tm then - mk[n] = tm[getchar(n)] + mk[n] = tm[n.char] end end end @@ -295,7 +272,7 @@ function injections.handler(head,where,keep) local cx = { } if has_kerns and next(ky) then for n, k in next, ky do - setfield(n,"yoffset",k) + n.yoffset = k end end -- todo: reuse t and use maxt @@ -306,9 +283,9 @@ function injections.handler(head,where,keep) for i=1,nofvalid do -- valid == glyphs local n = valid[i] if not mk[n] then - local n_cursbase = getattr(n,a_cursbase) + local n_cursbase = n[a_cursbase] if p_cursbase then - local n_curscurs = getattr(n,a_curscurs) + local n_curscurs = n[a_curscurs] if p_cursbase == n_curscurs then local c = cursives[n_curscurs] if c then @@ -333,20 +310,20 @@ function injections.handler(head,where,keep) end end elseif maxt > 0 then - local ny = getfield(n,"yoffset") + local ny = n.yoffset for i=maxt,1,-1 do ny = ny + d[i] local ti = t[i] - setfield(ti,"yoffset",getfield(ti,"yoffset") + ny) + ti.yoffset = ti.yoffset + ny end maxt = 0 end if not n_cursbase and maxt > 0 then - local ny = getfield(n,"yoffset") + local ny = n.yoffset for i=maxt,1,-1 do ny = ny + d[i] local ti = t[i] - setfield(ti,"yoffset",ny) + ti.yoffset = ny end maxt = 0 end @@ -354,11 +331,11 @@ function injections.handler(head,where,keep) end end if maxt > 0 then - local ny = getfield(n,"yoffset") + local ny = n.yoffset for i=maxt,1,-1 do ny = ny + d[i] local ti = t[i] - setfield(ti,"yoffset",ny) + ti.yoffset = ny end maxt = 0 end @@ -369,83 +346,57 @@ function injections.handler(head,where,keep) if has_marks then for i=1,nofvalid do local p = valid[i] - local p_markbase = getattr(p,a_markbase) + local p_markbase = p[a_markbase] if p_markbase then - local mrks = marks[p_markbase] - local nofmarks = #mrks - for n in traverse_id(glyph_code,getnext(p)) do - local n_markmark = getattr(n,a_markmark) + local mrks = marks[p_markbase] + local nofmarks = #mrks + for n in traverse_id(glyph_code,p.next) do + local n_markmark = n[a_markmark] if p_markbase == n_markmark then - local index = getattr(n,a_markdone) or 1 + local index = n[a_markdone] or 1 local d = mrks[index] if d then local rlmode = d[3] -- local k = wx[p] - local px = getfield(p,"xoffset") - local ox = 0 if k then local x = k[2] local w = k[4] if w then if rlmode and rlmode >= 0 then -- kern(x) glyph(p) kern(w-x) mark(n) - ox = px - getfield(p,"width") + d[1] - (w-x) - -- report_injections("l2r case 1: %p",ox) + n.xoffset = p.xoffset - p.width + d[1] - (w-x) else -- kern(w-x) glyph(p) kern(x) mark(n) - ox = px - d[1] - x - -- report_injections("r2l case 1: %p",ox) + n.xoffset = p.xoffset - d[1] - x end else if rlmode and rlmode >= 0 then -- okay for husayni - ox = px - getfield(p,"width") + d[1] - -- report_injections("r2l case 2: %p",ox) + n.xoffset = p.xoffset - p.width + d[1] else -- needs checking: is x ok here? - ox = px - d[1] - x - -- report_injections("r2l case 2: %p",ox) + n.xoffset = p.xoffset - d[1] - x end end else - -- if rlmode and rlmode >= 0 then - -- ox = px - getfield(p,"width") + d[1] - -- -- report_injections("l2r case 3: %p",ox) - -- else - -- ox = px - d[1] - -- -- report_injections("r2l case 3: %p",ox) - -- end - -- - -- we need to deal with fonts that have marks with width - -- - local wp = getfield(p,"width") - local wn = getfield(n,"width") -- in arial marks have widths if rlmode and rlmode >= 0 then - ox = px - wp + d[1] - -- report_injections("l2r case 3: %p",ox) + n.xoffset = p.xoffset - p.width + d[1] else - ox = px - d[1] - -- report_injections("r2l case 3: %p",ox) + n.xoffset = p.xoffset - d[1] end - if wn ~= 0 then - -- bad: we should center - insert_node_before(head,n,newkern(-wn/2)) - insert_node_after(head,n,newkern(-wn/2)) - -- wx[n] = { 0, -wn/2, 0, -wn } + local w = n.width + if w ~= 0 then + insert_node_before(head,n,newkern(-w/2)) + insert_node_after(head,n,newkern(-w/2)) end - -- so far end - setfield(n,"xoffset",ox) - -- - local py = getfield(p,"yoffset") - local oy = 0 + -- -- if mk[p] then - oy = py + d[2] + n.yoffset = p.yoffset + d[2] else - oy = getfield(n,"yoffset") + py + d[2] + n.yoffset = n.yoffset + p.yoffset + d[2] end - setfield(n,"yoffset",oy) -- if nofmarks == 1 then break @@ -453,8 +404,6 @@ function injections.handler(head,where,keep) nofmarks = nofmarks - 1 end end - elseif not n_markmark then - break -- HH: added 2013-09-12: no need to deal with non marks else -- KE: there can be <mark> <mkmk> <mark> sequences in ligatures end @@ -516,7 +465,6 @@ function injections.handler(head,where,keep) -- if trace_injections then -- show_result(head) -- end -head = tonode(head) return head, true elseif not keep then kerns, cursives, marks = { }, { }, { } @@ -526,14 +474,14 @@ head = tonode(head) trace(head) end for n in traverse_id(glyph_code,head) do - if getsubtype(n) < 256 then - local k = getattr(n,a_kernpair) + if n.subtype < 256 then + local k = n[a_kernpair] if k then local kk = kerns[k] if kk then local rl, x, y, w = kk[1], kk[2] or 0, kk[3], kk[4] if y and y ~= 0 then - setfield(n,"yoffset",y) -- todo: h ? + n.yoffset = y -- todo: h ? end if w then -- copied from above @@ -570,9 +518,9 @@ head = tonode(head) -- if trace_injections then -- show_result(head) -- end - return tonode(head), true + return head, true else -- no tracing needed end - return tonode(head), false + return head, false end diff --git a/tex/context/base/node-ltp.lua b/tex/context/base/node-ltp.lua index 9f2491cfa..c52e001df 100644 --- a/tex/context/base/node-ltp.lua +++ b/tex/context/base/node-ltp.lua @@ -18,6 +18,7 @@ if not modules then modules = { } end modules ['node-par'] = { -- todo: add a couple of plugin hooks -- todo: maybe split expansion code paths -- todo: fix line numbers (cur_list.pg_field needed) +-- todo: make kerns stretch an option and disable it by default (definitely not shrink) -- todo: check and improve protrusion -- todo: arabic etc (we could use pretty large scales there) .. marks and cursive @@ -72,8 +73,7 @@ if not modules then modules = { } end modules ['node-par'] = { To be honest, I slowly start to grasp the magic here as normally I start from scratch when implementing something (as it's the only way I can understand things). This time I had a recently acquired stack of - Porcupine Tree disks to get me through, although I must admit that watching their dvd's is more fun - than coding. + Porcupine Tree disks to get me through. Picking up this effort was inspired by discussions between Luigi Scarso and me about efficiency of Lua code and we needed some stress tests to compare regular LuaTeX and LuajitTeX. One of the tests was @@ -121,13 +121,6 @@ if not modules then modules = { } end modules ['node-par'] = { is enabled, but in the Lua variant the extra overhead is way less significant. This means that when we retrofit the same approach into the core, the overhead of expansion can be sort of nilled. - In 2013 the expansion factor method became also used at the TeX end so then I could complete the code - here, and indeed, expansions works quite well now (not compatible of course because we use floats at the - Lua end. The Lua base variant is still slower but quite ok, especially if we go nuts. - - A next iteration will provide plug-ins and more control. I will also explore the possibility to avoid the - redundant hpack calculations (easier now, although I've only done some quick and dirty experiments.) - ]]-- local utfchar = utf.char @@ -187,38 +180,22 @@ local chardata = fonthashes.characters local quaddata = fonthashes.quads local parameters = fonthashes.parameters -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getnext = nuts.getnext -local getprev = nuts.getprev -local getlist = nuts.getlist -local getfont = nuts.getfont -local getchar = nuts.getchar -local getattr = nuts.getattr - -local slide_nodelist = nuts.slide -- get rid of this, probably ok > 78.2 -local find_tail = nuts.tail -local new_node = nuts.new -local copy_node = nuts.copy -local copy_nodelist = nuts.copy_list -local flush_node = nuts.free -local flush_nodelist = nuts.flush_list -local hpack_nodes = nuts.hpack -local xpack_nodes = nuts.hpack -local replace_node = nuts.replace -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before -local traverse_by_id = nuts.traverse_id +local slide_nodes = node.slide +local new_node = node.new +local copy_node = node.copy +local copy_node_list = node.copy_list +local flush_node = node.free +local flush_node_list = node.flush_list +local hpack_nodes = node.hpack +local xpack_nodes = node.hpack +local replace_node = nodes.replace +local insert_node_after = node.insert_after +local insert_node_before = node.insert_before +local traverse_by_id = node.traverse_id local setnodecolor = nodes.tracers.colors.set -local nodepool = nuts.pool +local nodepool = nodes.pool local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -310,8 +287,7 @@ local glyphdir_is_equal = nodes.glyphdir_is_equal local dir_pops = nodes.dir_is_pop local dir_negations = nodes.dir_negation -local is_skipable = nuts.protrusion_skippable - +local is_skipable = node.protrusion_skippable local a_fontkern = attributes.private('fontkern') -- helpers -- @@ -332,12 +308,12 @@ local function checked_line_dir(stack,current) local n = stack.n + 1 stack.n = n stack[n] = current - return getfield(current,"dir") + return current.dir elseif n > 0 then local n = stack.n local dirnode = stack[n] dirstack.n = n - 1 - return getfield(dirnode,"dir") + return dirnode.dir else report_parbuilders("warning: missing pop node (%a)",1) -- in line ... end @@ -352,8 +328,8 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop) local n = stack.n local h = nil while start and start ~= stop do - if getid(start) == whatsit_code and getsubtype(start) == dir_code then - if not dir_pops[getfield(start,"dir")] then -- weird, what is this # + if start.id == whatsit_code and start.subtype == dir_code then + if not dir_pops[start.dir] then n = n + 1 stack[n] = start elseif n > 0 then @@ -362,10 +338,10 @@ local function inject_dirs_at_end_of_line(stack,current,start,stop) report_parbuilders("warning: missing pop node (%a)",2) -- in line ... end end - start = getnext(start) + start = start.next end for i=n,1,-1 do - h, current = insert_node_after(current,current,new_dir(dir_negations[getfield(stack[i],"dir")])) + h, current = insert_node_after(current,current,new_dir(dir_negations[stack[i].dir])) end stack.n = n return current @@ -414,8 +390,8 @@ local whatsiters = { local get_whatsit_width = whatsiters.get_width local get_whatsit_dimensions = whatsiters.get_dimensions -local function get_width (n,dir) return getfield(n,"width") end -local function get_dimensions(n,dir) return getfield(n,"width"), getfield(n,"height"), getfield(n,"depth") end +local function get_width (n) return n.width end +local function get_dimensions(n) return n.width, n.height, n.depth end get_whatsit_width[pdfrefximage_code] = get_width get_whatsit_width[pdfrefxform_code ] = get_width @@ -438,13 +414,13 @@ end local function check_shrinkage(par,n) -- called often, so maybe move inline -- use NORMAL - if getfield(n,"shrink_order") ~= 0 and getfield(n,"shrink") ~= 0 then + if n.shrink_order ~= 0 and n.shrink ~= 0 then if par.no_shrink_error_yet then par.no_shrink_error_yet = false report_parbuilders("infinite glue shrinkage found in a paragraph and removed") end n = copy_node(n) - setfield(n,"shrink_order",0) + n.shrink_order = 0 end return n end @@ -491,10 +467,48 @@ setmetatableindex(expansions,function(t,font) -- we can store this in tfmdata if end end) +-- local function char_stretch_shrink(p) +-- local data = expansions[p.font][p.char] +-- if data then +-- return data.glyphstretch, data.glyphshrink +-- else +-- return 0, 0 +-- end +-- end +-- +-- local cal_margin_kern_var = char_stretch_shrink + +-- local function kern_stretch_shrink(p,d) +-- local l = p.prev +-- if l and l.id == glyph_code then -- how about disc nodes? +-- local r = p.next +-- if r and r.id == glyph_code then +-- local lf, rf = l.font, r.font +-- if lf == rf then +-- local data = expansions[lf][l.char] +-- if data then +-- local stretch = data.stretch +-- local shrink = data.shrink +-- if stretch ~= 0 then +-- -- stretch = data.factor * (d * stretch - d) +-- stretch = data.factor * d * (stretch - 1) +-- end +-- if shrink ~= 0 then +-- -- shrink = data.factor * (d * shrink - d) +-- shrink = data.factor * d * (shrink - 1) +-- end +-- return stretch, shrink +-- end +-- end +-- end +-- end +-- return 0, 0 +-- end + local function kern_stretch_shrink(p,d) - local left = getprev(p) - if left and getid(left) == glyph_code then -- how about disc nodes? - local data = expansions[getfont(left)][getchar(left)] + local left = p.prev + if left and left.id == glyph_code then -- how about disc nodes? + local data = expansions[left.font][left.char] if data then local stretch = data.stretch local shrink = data.shrink @@ -512,8 +526,14 @@ local function kern_stretch_shrink(p,d) return 0, 0 end +-- local function kern_stretch_shrink(p,d) +-- -- maybe make it an option in luatex where we also need to check for attribute fontkern but in general +-- -- it makes no sense to scale kerns +-- return 0, 0 +-- end + local expand_kerns = false ------ expand_kerns = "both" +-- local expand_kerns = "both" directives.register("builders.paragraphs.adjusting.kerns",function(v) if not v then @@ -603,18 +623,18 @@ end local function find(head) -- do we really want to recurse into an hlist? while head do - local id = getid(head) + local id = head.id if id == glyph_code then return head elseif id == hlist_code then - local found = find(getlist(head)) + local found = find(head.list) if found then return found else - head = getnext(head) + head = head.next end elseif is_skipable(head) then - head = getnext(head) + head = head.next else return head end @@ -623,38 +643,38 @@ local function find(head) -- do we really want to recurse into an hlist? end local function find_protchar_left(l) -- weird function - local ln = getnext(l) - if ln and getid(ln) == hlist_code and not getlist(ln) and getfield(ln,"width") == 0 and getfield(ln,"height") == 0 and getfield(ln,"depth") == 0 then - l = getnext(l) + local ln = l.next + if ln and ln.id == hlist_code and not ln.list and ln.width == 0 and ln.height == 0 and ln.depth == 0 then + l = l.next else -- if d then -- was always true - local id = getid(l) + local id = l.id while ln and not (id == glyph_code or id < math_code) do -- is there always a glyph? l = ln - ln = getnext(l) - id = getid(ln) + ln = l.next + id = ln.id end end - -- if getid(l) == glyph_code then + -- if l.id == glyph_code then -- return l -- end return find(l) or l end local function find(head,tail) - local tail = tail or find_tail(head) + local tail = tail or slide_nodes(head) while tail do - local id = getid(tail) + local id = tail.id if id == glyph_code then return tail elseif id == hlist_code then - local found = find(getlist(tail)) + local found = find(tail.list) if found then return found else - tail = getprev(tail) + tail = tail.prev end elseif is_skipable(tail) then - tail = getprev(tail) + tail = tail.prev else return tail end @@ -667,8 +687,8 @@ local function find_protchar_right(l,r) end local function left_pw(p) - local font = getfont(p) - local prot = chardata[font][getchar(p)].left_protruding + local font = p.font + local prot = chardata[font][p.char].left_protruding if not prot or prot == 0 then return 0 end @@ -676,8 +696,8 @@ local function left_pw(p) end local function right_pw(p) - local font = getfont(p) - local prot = chardata[font][getchar(p)].right_protruding + local font = p.font + local prot = chardata[font][p.char].right_protruding if not prot or prot == 0 then return 0 end @@ -701,17 +721,17 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw local adjust_stretch = 0 local adjust_shrink = 0 while s do - local id = getid(s) + local id = s.id if id == glyph_code then if is_rotated[line_break_dir] then -- can be shared - size = size + getfield(s,"height") + getfield(s,"depth") + size = size + s.height + s.depth else - size = size + getfield(s,"width") + size = size + s.width end if checked_expansion then - local data = checked_expansion[getfont(s)] + local data = checked_expansion[s.font] if data then - data = data[getchar(s)] + data = data[s.char] if data then adjust_stretch = adjust_stretch + data.glyphstretch adjust_shrink = adjust_shrink + data.glyphshrink @@ -719,16 +739,16 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw end end elseif id == hlist_code or id == vlist_code then - if is_parallel[getfield(s,"dir")][line_break_dir] then - size = size + getfield(s,"width") + if is_parallel[s.dir][line_break_dir] then + size = size + s.width else - size = size + getfield(s,"height") + getfield(s,"depth") + size = size + s.depth + s.height end elseif id == kern_code then - local kern = getfield(s,"kern") - if kern ~= 0 then - if checked_expansion and expand_kerns and (getsubtype(s) == kerning_code or getattr(a_fontkern)) then - local stretch, shrink = kern_stretch_shrink(s,kern) + local d = s.kern + if d ~= 0 then + if checked_expansion and expand_kerns and (s.subtype == kerning_code or s[a_fontkern]) then + local stretch, shrink = kern_stretch_shrink(s,d) if expand_kerns == "stretch" then adjust_stretch = adjust_stretch + stretch elseif expand_kerns == "shrink" then @@ -738,14 +758,14 @@ local function add_to_width(line_break_dir,checked_expansion,s) -- split into tw adjust_shrink = adjust_shrink + shrink end end - size = size + kern + size = size + d end elseif id == rule_code then - size = size + getfield(s,"width") - elseif trace_unsupported then + size = size + s.width + else report_parbuilders("unsupported node at location %a",6) end - s = getnext(s) + s = s.next end return size, adjust_stretch, adjust_shrink end @@ -759,14 +779,14 @@ local function compute_break_width(par,break_type,p) -- split in two local break_size = break_width.size + disc_width.size local break_adjust_stretch = break_width.adjust_stretch + disc_width.adjust_stretch local break_adjust_shrink = break_width.adjust_shrink + disc_width.adjust_shrink - local replace = getfield(p,"replace") + local replace = p.replace if replace then local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace) break_size = break_size - size break_adjust_stretch = break_adjust_stretch - adjust_stretch break_adjust_shrink = break_adjust_shrink - adjust_shrink end - local post = getfield(p,"post") + local post = p.post if post then local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,post) break_size = break_size + size @@ -777,56 +797,56 @@ local function compute_break_width(par,break_type,p) -- split in two break_width.adjust_stretch = break_adjust_stretch break_width.adjust_shrink = break_adjust_shrink if not post then - p = getnext(p) + p = p.next else return end end while p do -- skip spacing etc - local id = getid(p) + local id = p.id if id == glyph_code then return -- happens often elseif id == glue_code then - local spec = getfield(p,"spec") - local order = stretch_orders[getfield(spec,"stretch_order")] - break_width.size = break_width.size - getfield(spec,"width") - break_width[order] = break_width[order] - getfield(spec,"stretch") - break_width.shrink = break_width.shrink - getfield(spec,"shrink") + local spec = p.spec + local order = stretch_orders[spec.stretch_order] + break_width.size = break_width.size - spec.width + break_width[order] = break_width[order] - spec.stretch + break_width.shrink = break_width.shrink - spec.shrink elseif id == penalty_code then -- do nothing elseif id == kern_code then - if getsubtype(p) == userkern_code then - break_width.size = break_width.size - getfield(p,"kern") + if p.subtype == userkern_code then + break_width.size = break_width.size - p.kern else return end elseif id == math_code then - break_width.size = break_width.size - getfield(p,"surround") + break_width.size = break_width.size - p.surround else return end - p = getnext(p) + p = p.next end end local function append_to_vlist(par, b) local prev_depth = par.prev_depth if prev_depth > par.ignored_dimen then - if getid(b) == hlist_code then - local d = getfield(par.baseline_skip,"width") - prev_depth - getfield(b,"height") -- deficiency of space between baselines - local s = d < par.line_skip_limit and new_lineskip(par.lineskip) or new_baselineskip(d) + if b.id == hlist_code then + local d = par.baseline_skip.width - prev_depth - b.height -- deficiency of space between baselines + local s = d < par.line_skip_limit and new_lineskip(tex.lineskip) or new_baselineskip(d) -- local s = d < par.line_skip_limit -- if s then -- s = new_lineskip() - -- setfield(s,"spec",tex.lineskip) + -- s.spec = tex.lineskip -- else -- s = new_baselineskip(d) -- end local head_field = par.head_field if head_field then - local n = slide_nodelist(head_field) -- todo: find_tail - setfield(n,"next",s) - setfield(s,"prev",n) + local n = slide_nodes(head_field) + n.next = s + s.prev = n else par.head_field = s end @@ -834,14 +854,14 @@ local function append_to_vlist(par, b) end local head_field = par.head_field if head_field then - local n = slide_nodelist(head_field) -- todo: find_tail - setfield(n,"next",b) - setfield(b,"prev",n) + local n = slide_nodes(head_field) + n.next = b + b.prev = n else par.head_field = b end - if getid(b) == hlist_code then - local pd = getfield(b,"depth") + if b.id == hlist_code then + local pd = b.depth par.prev_depth = pd texnest[texnest.ptr].prevdepth = pd end @@ -850,9 +870,9 @@ end local function append_list(par, b) local head_field = par.head_field if head_field then - local n = slide_nodelist(head_field) -- todo: find_tail - setfield(n,"next",b) - setfield(b,"prev",n) + local n = slide_nodes(head_field) + n.next = b + b.prev = n else par.head_field = b end @@ -864,18 +884,14 @@ end local hztolerance = 2500 local hzwarned = false -local function used_skip(s) - return s and (getfield(s,"width") ~= 0 or getfield(s,"stretch") ~= 0 or getfield(s,"shrink") ~= 0) and s or nil -end - local function initialize_line_break(head,display) local hang_indent = tex.hangindent or 0 local hsize = tex.hsize or 0 local hang_after = tex.hangafter or 0 local par_shape_ptr = tex.parshape - local left_skip = tonut(tex.leftskip) -- nodes - local right_skip = tonut(tex.rightskip) -- nodes + local left_skip = tex.leftskip -- nodes + local right_skip = tex.rightskip -- nodes local pretolerance = tex.pretolerance local tolerance = tex.tolerance local adjust_spacing = tex.pdfadjustspacing @@ -883,7 +899,7 @@ local function initialize_line_break(head,display) local last_line_fit = tex.lastlinefit local newhead = new_temp() - setfield(newhead,"next",head) + newhead.next = head local adjust_spacing_status = adjust_spacing > 1 and -1 or 0 @@ -950,13 +966,13 @@ local function initialize_line_break(head,display) last_line_depth = tex.pdflastlinedepth or 0, -- this will go away ignored_dimen = tex.pdfignoreddimen or 0, -- this will go away - baseline_skip = tonut(tex.baselineskip), - lineskip = tonut(tex.lineskip), - line_skip_limit = tex.lineskiplimit, + baseline_skip = tex.baselineskip or 0, + lineskip = tex.lineskip or 0, + line_skip_limit = tex.lineskiplimit or 0, prev_depth = texnest[texnest.ptr].prevdepth, - final_par_glue = slide_nodelist(head), -- todo: we know tail already, slow + final_par_glue = slide_nodes(head), -- todo: we know tail already, slow par_break_dir = tex.pardir, line_break_dir = tex.pardir, @@ -1025,13 +1041,6 @@ local function initialize_line_break(head,display) } - -- optimizers - - par.used_left_skip = used_skip(par.left_skip) - par.used_right_skip = used_skip(par.right_skip) - - -- so far - if adjust_spacing > 1 then local checked_expansion = { par = par } setmetatableindex(checked_expansion,check_expand_pars) @@ -1053,13 +1062,13 @@ local function initialize_line_break(head,display) local l = check_shrinkage(par,left_skip) local r = check_shrinkage(par,right_skip) - local l_order = stretch_orders[getfield(l,"stretch_order")] - local r_order = stretch_orders[getfield(r,"stretch_order")] + local l_order = stretch_orders[l.stretch_order] + local r_order = stretch_orders[r.stretch_order] - background.size = getfield(l,"width") + getfield(r,"width") - background.shrink = getfield(l,"shrink") + getfield(r,"shrink") - background[l_order] = getfield(l,"stretch") - background[r_order] = getfield(r,"stretch") + background[r_order] + background.size = l.width + r.width + background.shrink = l.shrink + r.shrink + background[l_order] = l.stretch + background[r_order] = r.stretch + background[r_order] -- this will move up so that we can assign the whole par table @@ -1139,192 +1148,185 @@ local function initialize_line_break(head,display) return par end --- there are still all kind of artefacts in here (a side effect I guess of pdftex, --- etex, omega and other extensions that got obscured by patching) - local function post_line_break(par) local prevgraf = texnest[texnest.ptr].prevgraf - local current_line = prevgraf + 1 -- the current line number being justified + local cur_line = prevgraf + 1 -- the current line number being justified + local cur_p = nil local adjust_spacing = par.adjust_spacing local protrude_chars = par.protrude_chars local statistics = par.statistics - local stack = new_dir_stack() - - local leftskip = par.used_left_skip -- used or normal ? - local rightskip = par.right_skip - local parshape = par.par_shape_ptr - local ignored_dimen = par.ignored_dimen - - local adapt_width = par.adapt_width + local p, s, k, w -- check when local - -- reverse the links of the relevant passive nodes, goto first breakpoint + local q = par.best_bet.break_node + repeat -- goto first breakpoint + local r = q + q = q.prev_break + r.prev_break = cur_p + cur_p = r + until not q - local current_break = nil + local stack = new_dir_stack() - local break_node = par.best_bet.break_node repeat - local first_break = break_node - break_node = break_node.prev_break - first_break.prev_break = current_break - current_break = first_break - until not break_node - - local head = par.head - - -- maybe : each_... - while current_break do + inject_dirs_at_begin_of_line(stack,par.head) - inject_dirs_at_begin_of_line(stack,head) + local q = nil + local r = cur_p.cur_break local disc_break = false local post_disc_break = false local glue_break = false - local lineend = nil -- q lineend refers to the last node of the line (and paragraph) - local lastnode = current_break.cur_break -- r lastnode refers to the node after which the dir nodes should be closed - - if not lastnode then - -- only at the end - lastnode = slide_nodelist(head) -- todo: find_tail - if lastnode == par.final_par_glue then - lineend = lastnode - lastnode = getprev(lastnode) + if not r then + r = slide_nodes(par.head) + if r == par.final_par_glue then + q = r -- q refers to the last node of the line (and paragraph) + r = r.prev -- r refers to the node after which the dir nodes should be closed end - else -- todo: use insert_list_after - local id = getid(lastnode) + else + local id = r.id if id == glue_code then - -- lastnode is normal skip - lastnode = replace_node(lastnode,new_rightskip(rightskip)) + -- r is normal skip + r = replace_node(r,new_rightskip(par.right_skip)) glue_break = true - lineend = lastnode - lastnode = getprev(r) + q = r -- q refers to the last node of the line + r = r.prev -- r refers to the node after which the dir nodes should be closed elseif id == disc_code then - local prevlast = getprev(lastnode) - local nextlast = getnext(lastnode) - local subtype = getsubtype(lastnode) - local pre = getfield(lastnode,"pre") - local post = getfield(lastnode,"post") - local replace = getfield(lastnode,"replace") + -- todo: use insert_before/after + local prev_r = r.prev + local next_r = r.next + local subtype = r.subtype + local pre = r.pre + local post = r.post + local replace = r.replace if subtype == second_disc_code then - if not (getid(prevlast) == disc_code and getsubtype(prevlast) == first_disc_code) then + if not (prev_r.id == disc_code and prev_r.subtype == first_disc_code) then report_parbuilders('unsupported disc at location %a',3) end if pre then - flush_nodelist(pre) - setfield(lastnode,"pre",nil) - pre = nil -- signal + flush_node_list(pre) + r.pre = nil + pre = nil -- signal end if replace then - local n = find_tail(replace) - setfield(prevlast,"next",replace) - setfield(replace,"prev",prevlast) - setfield(n,"next",lastnode) - setfield(lastnode,"prev",n) - setfield(lastnode,"replace",nil) - replace = nil -- signal + local n = slide_nodes(replace) + prev_r.next = replace + replace.prev = prev_r + n.next = r + r.prev = n + r.replace = nil + replace = nil -- signal end - local pre = getfield(prevlast,"pre") - local post = getfield(prevlast,"post") - local replace = getfield(prevlast,"replace") + local pre = prev_r.pre + local post = prev_r.post + local replace = prev_r.replace if pre then - flush_nodelist(pre) - setfield(prevlast,"pre",nil) + flush_node_list(pre) + prev_r.pre = nil end if replace then - flush_nodelist(replace) - setfield(prevlast,"replace",nil) + flush_node_list(replace) + prev_r.replace = nil end if post then - flush_nodelist(post) - setfield(prevlast,"post",nil) + flush_node_list(post) + prev_r.post = nil end elseif subtype == first_disc_code then - if not (getid(v) == disc_code and getsubtype(v) == second_disc_code) then + if not (v.id == disc_code and v.subtype == second_disc_code) then report_parbuilders('unsupported disc at location %a',4) end - setfield(nextlast,"subtype",regular_disc_code) - setfield(nextlast,"replace",post) - setfield(lastnode,"post",nil) + next_r.subtype = regular_disc_code + next_r.replace = post + r.post = nil end if replace then - setfield(lastnode,"replace",nil) -- free - flush_nodelist(replace) + r.replace = nil -- free + flush_node_list(replace) end if pre then - local n = find_tail(pre) - setfield(prevlast,"next",pre) - setfield(pre,"prev",prevlast) - setfield(n,"next",lastnode) - setfield(lastnode,"prev",n) - setfield(lastnode,"pre",nil) + local n = slide_nodes(pre) + prev_r.next = pre + pre.prev = prev_r + n.next = r + r.prev = n + r.pre = nil end if post then - local n = find_tail(post) - setfield(lastnode,"next",post) - setfield(post,"prev",lastnode) - setfield(n,"next",nextlast) - setfield(nextlast,"prev",n) - setfield(lastnode,"post",nil) + local n = slide_nodes(post) + r.next = post + post.prev = r + n.next = next_r + next_r.prev = n + r.post = nil post_disc_break = true end disc_break = true elseif id == kern_code then - setfield(lastnode,"kern",0) - elseif getid(lastnode) == math_code then - setfield(lastnode,"surround",0) + r.kern = 0 + elseif r.id == math_code then + r.surround = 0 end end - lastnode = inject_dirs_at_end_of_line(stack,lastnode,getnext(head),current_break.cur_break) - local rightbox = current_break.passive_right_box - if rightbox then - lastnode = insert_node_after(lastnode,lastnode,copy_node(rightbox)) + r = inject_dirs_at_end_of_line(stack,r,par.head.next,cur_p.cur_break) + local crb = cur_p.passive_right_box + if crb then + local s = copy_node(crb) + local e = r.next + r.next = s + s.prev = r + s.next = e + if e then + e.prev = s + end + r = s end - if not lineend then - lineend = lastnode + if not q then + q = r end - if lineend and lineend ~= head and protrude_chars > 0 then - local id = getid(lineend) - local c = (disc_break and (id == glyph_code or id ~= disc_code) and lineend) or getprev(lineend) - local p = find_protchar_right(getnext(head),c) - if p and getid(p) == glyph_code then + if q and q ~= par.head and protrude_chars > 0 then + local id = q.id + local c = (disc_break and (id == glyph_code or id ~= disc_code) and q) or q.prev + local p = find_protchar_right(par.head.next,c) + if p and p.id == glyph_code then local w, last_rightmost_char = right_pw(p) if last_rightmost_char and w ~= 0 then - -- so we inherit attributes, lineend is new pseudo head - lineend, c = insert_node_after(lineend,c,new_rightmarginkern(copy_node(last_rightmost_char),-w)) + -- so we inherit attributes, q is new pseudo head + q, c = insert_node_after(q,c,new_rightmarginkern(copy_node(last_rightmost_char),-w)) end end end - -- we finish the line - local r = getnext(lineend) - setfield(lineend,"next",nil) if not glue_break then - if rightskip then - insert_node_after(lineend,lineend,new_rightskip(right_skip)) -- lineend moves on as pseudo head - end - end - -- each time ? - local q = getnext(head) - setfield(head,"next",r) + local h + h, q = insert_node_after(q,q,new_rightskip(par.right_skip)) -- q moves on as pseudo head + end + r = q.next + q.next = nil + local phead = par.head + q = phead.next + phead.next = r if r then - setfield(r,"prev",head) - end - -- insert leftbox (if needed after parindent) - local leftbox = current_break.passive_left_box - if leftbox then - local first = getnext(q) - if first and current_line == (par.first_line + 1) and getid(first) == hlist_code and not getlist(first) then - insert_node_after(q,q,copy_node(leftbox)) - else - q = insert_node_before(q,q,copy_node(leftbox)) + r.prev = phead + end + local clb = cur_p.passive_left_box + if clb then -- here we miss some prev links + local s = copy_node(cb) + s = q.next + r.next = q + q = r + if s and cur_line == (par.first_line + 1) and s.id == hlist_code and not s.list then + q = q.next + r.next = s.next + s.next = r end end if protrude_chars > 0 then local p = find_protchar_left(q) - if p and getid(p) == glyph_code then + if p and p.id == glyph_code then local w, last_leftmost_char = left_pw(p) if last_leftmost_char and w ~= 0 then -- so we inherit attributes, q is pseudo head and moves back @@ -1332,35 +1334,32 @@ local function post_line_break(par) end end end - if leftskip then - q = insert_node_before(q,q,new_leftskip(leftskip)) + local ls = par.left_skip + if ls and (ls.width ~= 0 or ls.stretch ~= 0 or ls.shrink ~= 0) then + q = insert_node_before(q,q,new_leftskip(ls)) end - local cur_width, cur_indent - if current_line > par.last_special_line then + local curwidth, cur_indent + if cur_line > par.last_special_line then cur_indent = par.second_indent cur_width = par.second_width - elseif parshape then - local shape = parshape[current_line] - cur_indent = shape[1] - cur_width = shape[2] else - cur_indent = par.first_indent - cur_width = par.first_width - end - - if adapt_width then -- extension - local l, r = adapt_width(par,current_line) - cur_indent = cur_indent + l - cur_width = cur_width - l - r + local psp = par.par_shape_ptr + if psp then + cur_indent = psp[cur_line][1] + cur_width = psp[cur_line][2] + else + cur_indent = par.first_indent + cur_width = par.first_width + end end - statistics.noflines = statistics.noflines + 1 - local finished_line = nil if adjust_spacing > 0 then statistics.nofadjustedlines = statistics.nofadjustedlines + 1 - finished_line = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis) + -- in the built-in hpack cal_expand_ratio will later on call subst_ext_font + -- in the alternative approach we can do both in one run + just_box = xpack_nodes(q,cur_width,"cal_expand_ratio",par.par_break_dir) -- ,cur_p.analysis) else - finished_line = xpack_nodes(q,cur_width,"exactly",par.par_break_dir,par.first_line,current_line) -- ,current_break.analysis) + just_box = xpack_nodes(q,cur_width,"exactly",par.par_break_dir) -- ,cur_p.analysis) end if protrude_chars > 0 then statistics.nofprotrudedlines = statistics.nofprotrudedlines + 1 @@ -1369,42 +1368,39 @@ local function post_line_break(par) local adjust_head = texlists.adjust_head local pre_adjust_head = texlists.pre_adjust_head -- - setfield(finished_line,"shift",cur_indent) - -- this will probably go away: - if par.each_line_height ~= ignored_dimen then - setfield(finished_line,"height",par.each_line_height) + just_box.shift = cur_indent + if par.each_line_height ~= par.ignored_dimen then + just_box.height = par.each_line_height end - if par.each_line_depth ~= ignored_dimen then - setfield(finished_line,"depth",par.each_line_depth) + if par.each_line_depth ~= par.ignored_dimen then + just_box.depth = par.each_line_depth end - if par.first_line_height ~= ignored_dimen and (current_line == par.first_line + 1) then - setfield(finished_line,"height",par.first_line_height) + if par.first_line_height ~= par.ignored_dimen and (cur_line == par.first_line + 1) then + just_box.height = par.first_line_height end - if par.last_line_depth ~= ignored_dimen and current_line + 1 == par.best_line then - setfield(finished_line,"depth",par.last_line_depth) + if par.last_line_depth ~= par.ignored_dimen and cur_line + 1 == par.best_line then + just_box.depth = par.last_line_depth end - -- if texlists.pre_adjust_head ~= pre_adjust_head then append_list(par, texlists.pre_adjust_head) texlists.pre_adjust_head = pre_adjust_head end - append_to_vlist(par,finished_line) + append_to_vlist(par, just_box) if texlists.adjust_head ~= adjust_head then append_list(par, texlists.adjust_head) texlists.adjust_head = adjust_head end - -- local pen - if current_line + 1 ~= par.best_line then - if current_break.passive_pen_inter then - pen = current_break.passive_pen_inter + if cur_line + 1 ~= par.best_line then + if cur_p.passive_pen_inter then + pen = cur_p.passive_pen_inter else pen = par.inter_line_penalty end - if current_line == prevgraf + 1 then + if cur_line == prevgraf + 1 then pen = pen + par.club_penalty end - if current_line + 2 == par.best_line then + if cur_line + 2 == par.best_line then if par.display then pen = pen + par.display_widow_penalty else @@ -1412,58 +1408,56 @@ local function post_line_break(par) end end if disc_break then - if current_break.passive_pen_broken ~= 0 then - pen = pen + current_break.passive_pen_broken + if cur_p.passive_pen_broken ~= 0 then + pen = pen + cur_p.passive_pen_broken else pen = pen + par.broken_penalty end end if pen ~= 0 then append_to_vlist(par,new_penalty(pen)) - end + end end - current_line = current_line + 1 - current_break = current_break.prev_break - if current_break and not post_disc_break then - local current = head - local next = nil + cur_line = cur_line + 1 + cur_p = cur_p.prev_break + if cur_p and not post_disc_break then + local phead = par.head + local r = phead while true do - next = getnext(current) - if next == current_break.cur_break or getid(next) == glyph_code then + q = r.next + if q == cur_p.cur_break or q.id == glyph_code then break end - local id = getid(next) - local subtype = getsubtype(next) - if id == whatsit_code and subtype == localpar_code then - -- nothing - elseif id < math_code then - -- messy criterium - break - elseif id == kern_code and (subtype ~= userkern_code and not getattr(next,a_fontkern)) then - -- fontkerns and accent kerns as well as otf injections - break + local id = q.id + if not (id == whatsit_code and q.subtype == localpar_code) then + if id < math_code or (id == kern_code and q.subtype ~= userkern_code) then + break + end end - current = next + r = q end - if current ~= head then - setfield(current,"next",nil) - flush_nodelist(getnext(head)) - setfield(head,"next",next) - if next then - setfield(next,"prev",head) + if r ~= phead then + r.next = nil + flush_node_list(phead.next) + phead.next = q + if q then + q.prev = phead end end end + until not cur_p + if cur_line ~= par.best_line then -- or not par.head.next then + report_parbuilders("line breaking") end - -- if current_line ~= par.best_line then - -- report_parbuilders("line breaking") - -- end - par.head = nil -- needs checking - current_line = current_line - 1 + if par.head then -- added +-- flush_node(par.head) -- the localpar_code whatsit + par.head = nil + end + cur_line = cur_line - 1 if trace_basic then - report_parbuilders("paragraph broken into %a lines",current_line) + report_parbuilders("paragraph broken into %a lines",cur_line) end - texnest[texnest.ptr].prevgraf = current_line + texnest[texnest.ptr].prevgraf = cur_line end local function wrap_up(par) @@ -1481,11 +1475,11 @@ local function wrap_up(par) par.do_last_line_fit = false else local glue = par.final_par_glue - local spec = copy_node(getfield(glue,"spec")) - setfield(spec,"width",getfield(spec,"width") + active_short - active_glue) - setfield(spec,"stretch",0) - -- flush_node(getfield(glue,"spec")) -- brrr, when we do this we can get an "invalid id stretch message", maybe dec refcount - setfield(glue,"spec",spec) + local spec = copy_node(glue.spec) + spec.width = spec.width + active_short - active_glue + spec.stretch = 0 + -- flush_node(glue.spec) -- brrr, when we do this we can get an "invalid id stretch message", maybe dec refcount + glue.spec = spec if trace_lastlinefit then report_parbuilders("applying last line fit, short %a, glue %p",active_short,active_glue) end @@ -1493,8 +1487,8 @@ local function wrap_up(par) end -- we have a bunch of glue and and temp nodes not freed local head = par.head - if getid(head) == temp_code then - par.head = getnext(head) + if head.id == temp_code then + par.head = head.next flush_node(head) end post_line_break(par) @@ -1504,8 +1498,7 @@ local function wrap_up(par) end -- we could do active nodes differently ... table instead of linked list or a list --- with prev nodes but it doesn't save much (as we still need to keep indices then --- in next) +-- with prev nodes local function deactivate_node(par,prev_prev_r,prev_r,r,cur_active_width,checked_expansion) -- no need for adjust if disabled local active = par.active @@ -1623,26 +1616,18 @@ local function lastlinecrap(shortfall,active_short,active_glue,cur_active_width, end end --- todo: statistics .. count tries and so - -local trialcount = 0 - -local function try_break(pi, break_type, par, first_p, current, checked_expansion) - --- trialcount = trialcount + 1 --- print(trialcount,pi,break_type,current,nuts.tostring(current)) +local function try_break(pi, break_type, par, first_p, cur_p, checked_expansion) - if pi >= infinite_penalty then -- this breakpoint is inhibited by infinite penalty - local p_active = par.active - return p_active, p_active and p_active.next - elseif pi <= -infinite_penalty then -- this breakpoint will be forced - pi = eject_penalty + if pi >= infinite_penalty then + return -- this breakpoint is inhibited by infinite penalty + elseif pi <= -infinite_penalty then + pi = eject_penalty -- this breakpoint will be forced end local prev_prev_r = nil -- a step behind prev_r, if type(prev_r)=delta_code local prev_r = par.active -- stays a step behind r local r = nil -- runs through the active list - local no_break_yet = true -- have we found a feasible break at current? + local no_break_yet = true -- have we found a feasible break at cur_p? local node_r_stays_active = false -- should node r remain in the active list? local line_width = 0 -- the current line will be justified to this width local line_number = 0 -- line number of current active node @@ -1663,10 +1648,6 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio local tracing_paragraphs = par.tracing_paragraphs -- local par_active = par.active - local adapt_width = par.adapt_width - - local parshape = par.par_shape_ptr - local cur_active_width = checked_expansion and { -- distance from current active node size = active_width.size, stretch = active_width.stretch, @@ -1721,8 +1702,8 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio break_width.adjust_stretch = 0 break_width.adjust_shrink = 0 end - if current then - compute_break_width(par,break_type,current) + if cur_p then + compute_break_width(par,break_type,cur_p) end end if prev_r.id == delta_code then @@ -1788,14 +1769,14 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio end for fit_class = fit_very_loose_class, fit_tight_class do if minimal_demerits[fit_class] <= minimum_demerits then - -- insert a new active node from best_place[fit_class] to current + -- insert a new active node from best_place[fit_class] to cur_p par.pass_number = par.pass_number + 1 local prev_break = best_place[fit_class] local passive = { id = passive_code, subtype = nosubtype_code, next = par.passive, - cur_break = current, + cur_break = cur_p, serial = par.pass_number, prev_break = prev_break, passive_pen_inter = par.internal_pen_inter, @@ -1830,7 +1811,7 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio prev_r.next = q prev_r = q if tracing_paragraphs then - diagnostics.break_node(par,q,fit_class,break_type,current) + diagnostics.break_node(par,q,fit_class,break_type,cur_p) end end minimal_demerits[fit_class] = awful_badness @@ -1869,7 +1850,7 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio end end if r == par.active then - return r, r and r.next -- p_active, n_active + return end if line_number > par.easy_line then old_line_number = max_halfword - 1 @@ -1878,16 +1859,12 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio old_line_number = line_number if line_number > par.last_special_line then line_width = par.second_width - elseif parshape then - line_width = parshape[line_number][2] + elseif par.par_shape_ptr then + line_width = par.par_shape_ptr[line_number][2] else line_width = par.first_width end end - if adapt_width then - local l, r = adapt_width(par,line_number) - line_width = line_width - l - r - end end local artificial_demerits = false -- has d been forced to zero local shortfall = line_width - cur_active_width.size - par.internal_right_box_width -- used in badness calculations @@ -1901,17 +1878,17 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio -- this is quite time consuming local b = r.break_node local l = b and b.cur_break or first_p - local o = current and getprev(current) - if current and getid(current) == disc_code and getfield(current,"pre") then - o = find_tail(getfield(current,"pre")) + local o = cur_p and cur_p.prev + if cur_p and cur_p.id == disc_code and cur_p.pre then + o = slide_nodes(cur_p.pre) else o = find_protchar_right(l,o) end - if o and getid(o) == glyph_code then + if o and o.id == glyph_code then pw, rp = right_pw(o) shortfall = shortfall + pw end - local id = getid(l) + local id = l.id if id == glyph_code then -- ok ? elseif id == disc_code and l.post then @@ -1919,7 +1896,7 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio else l = find_protchar_left(l) end - if l and getid(l) == glyph_code then + if l and l.id == glyph_code then pw, lp = left_pw(l) shortfall = shortfall + pw end @@ -1929,23 +1906,27 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio local margin_kern_shrink = 0 if protrude_chars > 1 then if lp then - local data = expansions[getfont(lp)][getchar(lp)] - if data then - margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink - end +-- margin_kern_stretch, margin_kern_shrink = cal_margin_kern_var(lp) +local data = expansions[lp.font][lp.char] +if data then + margin_kern_stretch, margin_kern_shrink = data.glyphstretch, data.glyphshrink +end end if rp then - local data = expansions[getfont(lp)][getchar(lp)] - if data then - margin_kern_stretch = margin_kern_stretch + data.glyphstretch - margin_kern_shrink = margin_kern_shrink + data.glyphshrink - end +-- local mka, mkb = cal_margin_kern_var(rp) +-- margin_kern_stretch = margin_kern_stretch + mka +-- margin_kern_shrink = margin_kern_shrink + mkb +local data = expansions[lp.font][lp.char] +if data then + margin_kern_stretch = margin_kern_stretch + data.glyphstretch + margin_kern_shrink = margin_kern_shrink + data.glyphshrink +end end end local total = cur_active_width.adjust_stretch + margin_kern_stretch if shortfall > 0 and total > 0 then if total > shortfall then - shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2 + shortfall = total / (par.max_stretch_ratio / par.cur_font_step) / 2 -- to be adapted else shortfall = shortfall - total end @@ -1953,7 +1934,7 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio total = cur_active_width.adjust_shrink + margin_kern_shrink if shortfall < 0 and total > 0 then if total > - shortfall then - shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2 + shortfall = - total / (par.max_shrink_ratio / par.cur_font_step) / 2 -- to be adapted else shortfall = shortfall + total end @@ -1968,7 +1949,7 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio if cur_active_width.fi ~= 0 or cur_active_width.fil ~= 0 or cur_active_width.fill ~= 0 or cur_active_width.filll ~= 0 then if not do_last_line_fit then -- okay - elseif not current then + elseif not cur_p then found, shortfall, fit_class, g, b = lastlinecrap(shortfall,r.active_short,r.active_glue,cur_active_width,par.fill_width,par.last_line_fit) else shortfall = 0 @@ -2003,7 +1984,7 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio end end if do_last_line_fit and not found then - if not current then + if not cur_p then -- g = 0 shortfall = 0 elseif shortfall > 0 then @@ -2051,7 +2032,7 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio d = d - pi * pi end if break_type == hyphenated_code and r.id == hyphenated_code then - if current then + if cur_p then d = d + par.double_hyphen_demerits else d = d + par.final_hyphen_demerits @@ -2063,9 +2044,9 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio end end if tracing_paragraphs then - diagnostics.feasible_break(par,current,r,b,pi,d,artificial_demerits) + diagnostics.feasible_break(par,cur_p,r,b,pi,d,artificial_demerits) end - d = d + r.total_demerits -- this is the minimum total demerits from the beginning to current via r + d = d + r.total_demerits -- this is the minimum total demerits from the beginning to cur_p via r if d <= minimal_demerits[fit_class] then minimal_demerits[fit_class] = d best_place [fit_class] = r.break_node @@ -2089,16 +2070,25 @@ local function try_break(pi, break_type, par, first_p, current, checked_expansio end end +local function kern_break(par, cur_p, first_p, checked_expansion) -- move inline if needed + local v = cur_p.next + if par.auto_breaking and v.id == glue_code then + try_break(0, unhyphenated_code, par, first_p, cur_p, checked_expansion) + end + local active_width = par.active_width + if cur_p.id ~= math_code then + active_width.size = active_width.size + cur_p.kern + else + active_width.size = active_width.size + cur_p.surround + end +end + -- we can call the normal one for simple box building in the otr so we need -- frequent enabling/disabling -local dcolor = { [0] = "red", "green", "blue", "magenta", "cyan", "gray" } - local temp_head = new_temp() function constructors.methods.basic(head,d) - head = tonut(head) - if trace_basic then report_parbuilders("starting at %a",head) end @@ -2150,27 +2140,24 @@ function constructors.methods.basic(head,d) par.passive = nil -- = 0 par.printed_node = temp_head -- only when tracing, shared + par.printed_node.next = head par.pass_number = 0 --- par.auto_breaking = true - - setfield(temp_head,"next",head) - - local current = head - local first_p = current + par.auto_breaking = true - local auto_breaking = true + local cur_p = head + local first_p = cur_p par.font_in_short_display = 0 - if current and getid(current) == whatsit_code and getsubtype(current) == localpar_code then - par.init_internal_left_box = getfield(current,"box_left") - par.init_internal_left_box_width = getfield(current,"box_left_width") - par.internal_pen_inter = getfield(current,"pen_inter") - par.internal_pen_broken = getfield(current,"pen_broken") + if cur_p and cur_p.id == whatsit_code and cur_p.subtype == localpar_code then + par.init_internal_left_box = cur_p.box_left + par.init_internal_left_box_width = cur_p.box_left_width + par.internal_pen_inter = cur_p.pen_inter + par.internal_pen_broken = cur_p.pen_broken par.internal_left_box = par.init_internal_left_box par.internal_left_box_width = par.init_internal_left_box_width - par.internal_right_box = getfield(current,"box_right") - par.internal_right_box_width = getfield(current,"box_right_width") + par.internal_right_box = cur_p.box_right + par.internal_right_box_width = cur_p.box_right_width end -- all passes are combined in this loop so maybe we should split this into @@ -2182,34 +2169,23 @@ function constructors.methods.basic(head,d) local fontexp, lastfont -- we can pass fontexp to calculate width if needed - -- i flattened the inner loop over glyphs .. it looks nicer and the extra p_active ~= n_active - -- test is fast enough (and try_break now returns the updated values); the kern helper has been - -- inlined as it did a double check on id so in fact we had hardly any code to share - - local p_active = par.active - local n_active = p_active and p_active.next - local second_pass = par.second_pass - - trialcount = 0 - - while current and p_active ~= n_active do - local id = getid(current) - if id == glyph_code then + while cur_p and par.active.next ~= par.active do + while cur_p and cur_p.id == glyph_code do if is_rotated[par.line_break_dir] then - active_width.size = active_width.size + getfield(current,"height") + getfield(current,"depth") + active_width.size = active_width.size + cur_p.height + cur_p.depth else - active_width.size = active_width.size + getfield(current,"width") + active_width.size = active_width.size + cur_p.width end if checked_expansion then - local currentfont = getfont(current) - local data= checked_expansion[currentfont] + local data= checked_expansion[cur_p.font] if data then + local currentfont = cur_p.font if currentfont ~= lastfont then fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer lastfont = currentfont end if fontexps then - local expansion = fontexps[getchar(current)] + local expansion = fontexps[cur_p.char] if expansion then active_width.adjust_stretch = active_width.adjust_stretch + expansion.glyphstretch active_width.adjust_shrink = active_width.adjust_shrink + expansion.glyphshrink @@ -2217,45 +2193,51 @@ function constructors.methods.basic(head,d) end end end - elseif id == hlist_code or id == vlist_code then - if is_parallel[getfield(current,"dir")][par.line_break_dir] then - active_width.size = active_width.size + getfield(current,"width") + cur_p = cur_p.next + end + if not cur_p then -- TODO + report_parbuilders("problems with linebreak_tail") + os.exit() + end + local id = cur_p.id + if id == hlist_code or id == vlist_code then + if is_parallel[cur_p.dir][par.line_break_dir] then + active_width.size = active_width.size + cur_p.width else - active_width.size = active_width.size + getfield(current,"depth") + getfield(current,"height") + active_width.size = active_width.size + cur_p.depth + cur_p.height end elseif id == glue_code then --- if par.auto_breaking then - if auto_breaking then - local prev_p = getprev(current) + if par.auto_breaking then + local prev_p = cur_p.prev if prev_p and prev_p ~= temp_head then - local id = getid(prev_p) + local id = prev_p.id if id == glyph_code or - (id < math_code and (id ~= whatsit_code or getsubtype(prev_p) ~= dir_code)) or -- was: precedes_break(prev_p) - (id == kern_code and getsubtype(prev_p) ~= userkern_code) then - p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) + (id < math_code and (id ~= whatsit_code or prev_p.subtype ~= dir_code)) or -- was: precedes_break(prev_p) + (id == kern_code and prev_p.subtype ~= userkern_code) then + try_break(0, unhyphenated_code, par, first_p, cur_p, checked_expansion) end end end - local spec = check_shrinkage(par,getfield(current,"spec")) - local order = stretch_orders[getfield(spec,"stretch_order")] - setfield(current,"spec",spec) - active_width.size = active_width.size + getfield(spec,"width") - active_width[order] = active_width[order] + getfield(spec,"stretch") - active_width.shrink = active_width.shrink + getfield(spec,"shrink") + local spec = check_shrinkage(par,cur_p.spec) + local order = stretch_orders[spec.stretch_order] + cur_p.spec = spec + active_width.size = active_width.size + spec.width + active_width[order] = active_width[order] + spec.stretch + active_width.shrink = active_width.shrink + spec.shrink elseif id == disc_code then - local subtype = getsubtype(current) - if subtype ~= second_disc_code then + local subtype = cur_p.subtype + if subtype ~= second_disc_code then -- are there still second_disc_code in luatex local line_break_dir = par.line_break_dir - if second_pass or subtype <= automatic_disc_code then + if par.second_pass then -- todo: make second pass local local actual_pen = subtype == automatic_disc_code and par.ex_hyphen_penalty or par.hyphen_penalty - local pre = getfield(current,"pre") + local pre = cur_p.pre if not pre then -- trivial pre-break disc_width.size = 0 if checked_expansion then disc_width.adjust_stretch = 0 disc_width.adjust_shrink = 0 end - p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion) + try_break(actual_pen, hyphenated_code, par, first_p, cur_p, checked_expansion) else local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre) disc_width.size = size @@ -2269,13 +2251,13 @@ function constructors.methods.basic(head,d) -- disc_width.adjust_stretch = 0 -- disc_width.adjust_shrink = 0 end - p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, current, checked_expansion) + try_break(actual_pen, hyphenated_code, par, first_p, cur_p, checked_expansion) if subtype == first_disc_code then - local cur_p_next = getnext(current) - if getid(cur_p_next) ~= disc_code or getsubtype(cur_p_next) ~= second_disc_code then + local cur_p_next = cur_p.next + if cur_p_next.id ~= disc_code or cur_p_next.subtype ~= second_disc_code then report_parbuilders("unsupported disc at location %a",1) else - local pre = getfield(cur_p_next,"pre") + local pre = cur_p_next.pre if pre then local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,pre) disc_width.size = disc_width.size + size @@ -2283,16 +2265,16 @@ function constructors.methods.basic(head,d) disc_width.adjust_stretch = disc_width.adjust_stretch + adjust_stretch disc_width.adjust_shrink = disc_width.adjust_shrink + adjust_shrink end - p_active, n_active = try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion) + try_break(actual_pen, hyphenated_code, par, first_p, cur_p_next, checked_expansion) -- -- I will look into this some day ... comment in linebreak.w says that this fails, -- maybe this is what Taco means with his comment in the luatex manual. -- -- do_one_seven_eight(sub_disc_width_from_active_width); -- do_one_seven_eight(reset_disc_width); - -- s = vlink_no_break(vlink(current)); + -- s = vlink_no_break(vlink(cur_p)); -- add_to_widths(s, line_break_dir, pdf_adjust_spacing,disc_width); - -- ext_try_break(...,first_p,vlink(current)); + -- ext_try_break(...,first_p,vlink(cur_p)); -- else report_parbuilders("unsupported disc at location %a",2) @@ -2307,7 +2289,7 @@ function constructors.methods.basic(head,d) end end end - local replace = getfield(current,"replace") + local replace = cur_p.replace if replace then local size, adjust_stretch, adjust_shrink = add_to_width(line_break_dir,checked_expansion,replace) active_width.size = active_width.size + size @@ -2318,20 +2300,14 @@ function constructors.methods.basic(head,d) end end elseif id == kern_code then - if getsubtype(current) == userkern_code then - local v = getnext(current) --- if par.auto_breaking and getid(v) == glue_code then - if auto_breaking and getid(v) == glue_code then - p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) - end - local active_width = par.active_width - active_width.size = active_width.size + getfield(current,"kern") + if cur_p.subtype == userkern_code then + kern_break(par,cur_p,first_p, checked_expansion) else - local kern = getfield(current,"kern") - if kern ~= 0 then - active_width.size = active_width.size + kern - if checked_expansion and expand_kerns and (getsubtype(current) == kerning_code or getattr(current,a_fontkern)) then - local stretch, shrink = kern_stretch_shrink(current,kern) + local d = cur_p.kern + of d ~= 0 then + active_width.size = active_width.size + d + if checked_expansion and expand_kerns and (cur_p.subtype == kerning_code or cur_p[a_fontkern]) then + local stretch, shrink = kern_stretch_shrink(cur_p,d) if expand_kerns == "stretch" then active_width.adjust_stretch = active_width.adjust_stretch + stretch elseif expand_kerns == "shrink" then @@ -2344,47 +2320,40 @@ function constructors.methods.basic(head,d) end end elseif id == math_code then --- par.auto_breaking = getsubtype(current) == endmath_code - auto_breaking = getsubtype(current) == endmath_code - local v = getnext(current) --- if par.auto_breaking and getid(v) == glue_code then - if auto_breaking and getid(v) == glue_code then - p_active, n_active = try_break(0, unhyphenated_code, par, first_p, current, checked_expansion) - end - local active_width = par.active_width - active_width.size = active_width.size + getfield(current,"surround") + par.auto_breaking = cur_p.subtype == endmath_code + kern_break(par,cur_p, first_p, checked_expansion) elseif id == rule_code then - active_width.size = active_width.size + getfield(current,"width") + active_width.size = active_width.size + cur_p.width elseif id == penalty_code then - p_active, n_active = try_break(getfield(current,"penalty"), unhyphenated_code, par, first_p, current, checked_expansion) + try_break(cur_p.penalty, unhyphenated_code, par, first_p, cur_p, checked_expansion) elseif id == whatsit_code then - local subtype = getsubtype(current) + local subtype = cur_p.subtype if subtype == localpar_code then - par.internal_pen_inter = getfield(current,"pen_inter") - par.internal_pen_broken = getfield(current,"pen_broken") - par.internal_left_box = getfield(current,"box_left") - par.internal_left_box_width = getfield(current,"box_left_width") - par.internal_right_box = getfield(current,"box_right") - par.internal_right_box_width = getfield(current,"box_right_width") + par.internal_pen_inter = cur_p.pen_inter + par.internal_pen_broken = cur_p.pen_broken + par.internal_left_box = cur_p.box_left + par.internal_left_box_width = cur_p.box_left_width + par.internal_right_box = cur_p.box_right + par.internal_right_box_width = cur_p.box_right_width elseif subtype == dir_code then par.line_break_dir = checked_line_dir(dirstack) or par.line_break_dir else local get_width = get_whatsit_width[subtype] if get_width then - active_width.size = active_width.size + get_width(current,par.line_break_dir) + active_width.size = active_width.size + get_width(cur_p) end end - elseif trace_unsupported then - if id == mark_code or id == ins_code or id == adjust_code then - -- skip - else - report_parbuilders("node of type %a found in paragraph",type(id)) - end + elseif id == mark_code or id == ins_code or id == adjust_code then + -- skip + else + report_parbuilders("node of type %a found in paragraph",type(id)) end - current = getnext(current) + cur_p = cur_p.next end - if not current then - local p_active, n_active = try_break(eject_penalty, hyphenated_code, par, first_p, current, checked_expansion) + if not cur_p then + try_break(eject_penalty, hyphenated_code, par, first_p, cur_p, checked_expansion) + local p_active = par.active + local n_active = p_active.next if n_active ~= p_active then local r = n_active par.fewest_demerits = awful_badness @@ -2398,7 +2367,7 @@ function constructors.methods.basic(head,d) par.best_line = par.best_bet.line_number local asked_looseness = par.looseness if asked_looseness == 0 then - return tonode(wrap_up(par)) + return wrap_up(par) end local r = n_active local actual_looseness = 0 @@ -2418,30 +2387,30 @@ function constructors.methods.basic(head,d) end end r = r.next - until r == p_active + until r == p_active -- weird, loop list? par.best_line = par.best_bet.line_number if actual_looseness == asked_looseness or par.final_pass then - return tonode(wrap_up(par)) + return wrap_up(par) end end end reset_meta(par) -- clean up the memory by removing the break nodes - if not second_pass then + if not par.second_pass then if tracing_paragraphs then diagnostics.current_pass(par,"secondpass") end - par.threshold = par.tolerance + par.threshold = par.tolerance par.second_pass = true - par.final_pass = par.emergency_stretch <= 0 + par.final_pass = par.emergency_stretch <= 0 else if tracing_paragraphs then diagnostics.current_pass(par,"emergencypass") end par.background.stretch = par.background.stretch + par.emergency_stretch - par.final_pass = true + par.final_pass = true end end - return tonode(wrap_up(par)) + return wrap_up(par) end -- standard tex logging .. will be adapted .. @@ -2466,58 +2435,48 @@ function diagnostics.current_pass(par,what) write_nl("log",format("@%s",what)) end -local verbose = false -- true - -local function short_display(target,a,font_in_short_display) +local function short_display(a,font_in_short_display) while a do - local id = getid(a) + local id = a.id if id == glyph_code then - local font = getfont(a) + local font = a.font if font ~= font_in_short_display then - write(target,tex.fontidentifier(font) .. ' ') + write("log",tex.fontidentifier(font) .. ' ') font_in_short_display = font end - if getsubtype(a) == ligature_code then - font_in_short_display = short_display(target,getfield(a,"components"),font_in_short_display) + if a.subtype == ligature_code then + font_in_short_display = short_display(a.components,font_in_short_display) else - write(target,utfchar(getchar(a))) + write("log",utfchar(a.char)) end +-- elseif id == rule_code then +-- write("log","|") +-- elseif id == glue_code then +-- if a.spec.writable then +-- write("log"," ") +-- end +-- elseif id == math_code then +-- write("log","$") elseif id == disc_code then - font_in_short_display = short_display(target,getfield(a,"pre"),font_in_short_display) - font_in_short_display = short_display(target,getfield(a,"post"),font_in_short_display) - elseif verbose then - write(target,format("[%s]",nodecodes[id])) - elseif id == rule_code then - write(target,"|") - elseif id == glue_code then - if getfield(getfield(a,"spec"),"writable") then - write(target," ") - end - elseif id == kern_code and (getsubtype(a) == userkern_code or getattr(a,a_fontkern)) then - if verbose then - write(target,"[|]") - else - write(target,"") - end - elseif id == math_code then - write(target,"$") - else - write(target,"[]") + font_in_short_display = short_display(a.pre,font_in_short_display) + font_in_short_display = short_display(a.post,font_in_short_display) + else -- no explicit checking + write("log",format("[%s]",nodecodes[id])) end - a = getnext(a) + a = a.next end return font_in_short_display end diagnostics.short_display = short_display -function diagnostics.break_node(par, q, fit_class, break_type, current) -- %d ? +function diagnostics.break_node(par, q, fit_class, break_type, cur_p) -- %d ? local passive = par.passive local typ_ind = break_type == hyphenated_code and '-' or "" if par.do_last_line_fit then local s = number.toscaled(q.active_short) local g = number.toscaled(q.active_glue) - if current then + if cur_p then write_nl("log",format("@@%d: line %d.%d%s t=%s s=%s g=%s", passive.serial or 0,q.line_number-1,fit_class,typ_ind,q.total_demerits,s,g)) else @@ -2535,26 +2494,26 @@ function diagnostics.break_node(par, q, fit_class, break_type, current) -- %d ? end end -function diagnostics.feasible_break(par, current, r, b, pi, d, artificial_demerits) +function diagnostics.feasible_break(par, cur_p, r, b, pi, d, artificial_demerits) local printed_node = par.printed_node - if printed_node ~= current then + if printed_node ~= cur_p then write_nl("log","") - if not current then - par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display) + if not cur_p then + par.font_in_short_display = short_display(printed_node.next,par.font_in_short_display) else - local save_link = getnext(current) - setfield(cur_p,"next",nil) + local save_link = cur_p.next + cur_p.next = nil write_nl("log","") - par.font_in_short_display = short_display("log",getnext(printed_node),par.font_in_short_display) - setfield(cur_p,"next",save_link) + par.font_in_short_display = short_display(printed_node.next,par.font_in_short_display) + cur_p.next = save_link end - par.printed_node = current + par.printed_node = cur_p end write_nl("log","@") - if not current then + if not cur_p then write_esc("par") else - local id = getid(current) + local id = cur_p.id if id == glue_code then -- print nothing elseif id == penalty_code then @@ -2603,54 +2562,49 @@ end) -- with the glyph. local function glyph_width_height_depth(curdir,pdir,p) - local wd = getfield(p,"width") - local ht = getfield(p,"height") - local dp = getfield(p,"depth") if is_rotated[curdir] then if is_parallel[curdir][pdir] then - local half = (ht + dp) / 2 - return wd, half, half + local half = (p.height + p.depth) / 2 + return p.width, half, half else - local half = wd / 2 - return ht + dp, half, half + local half = p.width / 2 + return p.height + p.depth, half, half end elseif is_rotated[pdir] then if is_parallel[curdir][pdir] then - local half = (ht + dp) / 2 - return wd, half, half + local half = (p.height + p.depth) / 2 + return p.width, half, half else - return ht + dp, wd, 0 -- weird + return p.height + p.depth, p.width, 0 -- weird end else if glyphdir_is_equal[curdir][pdir] then - return wd, ht, dp + return p.width, p.height, p.depth elseif is_opposite[curdir][pdir] then - return wd, dp, ht + return p.width, p.depth, p.height else -- can this happen? - return ht + dp, wd, 0 + return p.height + p.depth, p.width, 0 -- weird end end end local function pack_width_height_depth(curdir,pdir,p) - local wd = getfield(p,"width") - local ht = getfield(p,"height") - local dp = getfield(p,"depth") if is_rotated[curdir] then if is_parallel[curdir][pdir] then - local half = (ht + dp) / 2 - return wd, half, half + local half = (p.height + p.depth) / 2 + return p.width, half, half else -- can this happen? - local half = wd / 2 - return ht + dp, half, half + local half = p.width / 2 + return p.height + p.depth, half, half end else if pardir_is_equal[curdir][pdir] then - return wd, ht, dp + return p.width, p.height, p.depth elseif is_opposite[curdir][pdir] then - return wd, dp, ht + return p.width, p.depth, p.height else -- weird dimensions, can this happen? - return ht + dp, wd, 0 + -- return p.width, p.depth, p.height + return p.height + p.depth, p.width, 0 end end end @@ -2668,17 +2622,17 @@ end -- -- local hlist = new_node("hlist") -- --- setfield(hlist,"list",head) --- setfield(hlist,"dir",direction or tex.textdir) --- setfield(hlist,"width",width) --- setfield(hlist,"height",height) --- setfield(hlist,"depth",depth) +-- hlist.list = head +-- hlist.dir = direction or tex.textdir +-- hlist.width = width +-- hlist.height = height +-- hlist.depth = depth -- -- if delta == 0 then -- --- setfield(hlist,"glue_sign",0) --- setfield(hlist,"glue_order",0) --- setfield(hlist,"glue_set",0) +-- hlist.glue_sign = 0 +-- hlist.glue_order = 0 +-- hlist.glue_set = 0 -- -- else -- @@ -2694,15 +2648,16 @@ end -- else -- local stretch = analysis.stretch -- if stretch ~= 0 then --- setfield(hlist,"glue_sign",1) -- stretch --- setfield(hlist,"glue_order",order) --- setfield(hlist,"glue_set",delta/stretch) +-- hlist.glue_sign = 1 -- stretch +-- hlist.glue_order = order +-- hlist.glue_set = delta/stretch -- else --- setfield(hlist,"glue_sign",0) -- nothing --- setfield(hlist,"glue_order",order) --- setfield(hlist,"glue_set",0) +-- hlist.glue_sign = 0 -- nothing +-- hlist.glue_order = order +-- hlist.glue_set = 0 -- end -- end +-- print("stretch",hlist.glue_sign,hlist.glue_order,hlist.glue_set) -- -- else -- @@ -2711,15 +2666,16 @@ end -- else -- local shrink = analysis.shrink -- if shrink ~= 0 then --- setfield(hlist,"glue_sign",2) -- shrink --- setfield(hlist,"glue_order",order) --- setfield(hlist,"glue_set",-delta/stretch) +-- hlist.glue_sign = 2 -- shrink +-- hlist.glue_order = order +-- hlist.glue_set = - delta/shrink -- else --- setfield(hlist,"glue_sign",0) -- nothing --- setfield(hlist,"glue_order",order) --- setfield(hlist,"glue_set",0) +-- hlist.glue_sign = 0 -- nothing +-- hlist.glue_order = order +-- hlist.glue_set = 0 -- end -- end +-- print("shrink",hlist.glue_sign,hlist.glue_order,hlist.glue_set) -- -- end -- @@ -2733,7 +2689,7 @@ end -- end -- local current = head -- while current do --- local id = getid(current) +-- local id = current.id -- if id == glyph_code then -- local stretch, shrink = char_stretch_shrink(current) -- get only one -- if stretch then @@ -2743,12 +2699,12 @@ end -- current.expansion_factor = font_expand_ratio * stretch -- end -- elseif id == kern_code then --- local kern = getfield(current,"kern") --- if kern ~= 0 and getsubtype(current) == kerning_code then --- setfield(current,"kern",font_expand_ratio * kern) +-- local kern = current.kern +-- if kern ~= 0 and current.subtype == kerning_code then +-- current.kern = font_expand_ratio * current.kern -- end -- end --- current = getnext(current) +-- current = current.next -- end -- elseif font_expand_ratio < 0 then -- if font_expand_ratio < -1000 then @@ -2756,7 +2712,7 @@ end -- end -- local current = head -- while current do --- local id = getid(current) +-- local id = current.id -- if id == glyph_code then -- local stretch, shrink = char_stretch_shrink(current) -- get only one -- if shrink then @@ -2766,31 +2722,26 @@ end -- current.expansion_factor = font_expand_ratio * shrink -- end -- elseif id == kern_code then --- local kern = getfield(current,"kern") --- if kern ~= 0 and getsubtype(current) == kerning_code then --- setfield(current,"kern",font_expand_ratio * kern) +-- local kern = current.kern +-- if kern ~= 0 and current.subtype == kerning_code then +-- current.kern = font_expand_ratio * current.kern -- end -- end --- current = getnext(current) +-- current = current.next -- end -- end -- return hlist, 0 -- end -local function hpack(head,width,method,direction,firstline,line) -- fast version when head = nil +local function hpack(head,width,method,direction) -- fast version when head = nil -- we can pass the adjust_width and adjust_height so that we don't need to recalculate them but - -- with the glue mess it's less trivial as we lack detail .. challenge + -- with the glue mess it's less trivial as we lack detail local hlist = new_node("hlist") - setfield(hlist,"dir",direction) - if head == nil then - setfield(hlist,"width",width) return hlist, 0 - else - setfield(hlist,"list",head) end local cal_expand_ratio = method == "cal_expand_ratio" or method == "subst_ex_font" @@ -2806,6 +2757,8 @@ local function hpack(head,width,method,direction,firstline,line) -- fast version local font_shrink = 0 local font_expand_ratio = 0 local last_badness = 0 + local disc_stack = { } + local disc_level = 0 local expansion_stack = cal_expand_ratio and { } -- todo: optionally pass this local expansion_index = 0 local total_stretch = { [0] = 0, 0, 0, 0, 0 } @@ -2815,8 +2768,11 @@ local function hpack(head,width,method,direction,firstline,line) -- fast version local adjust_head = texlists.adjust_head local pre_adjust_head = texlists.pre_adjust_head - local adjust_tail = adjust_head and slide_nodelist(adjust_head) -- todo: find_tail - local pre_adjust_tail = pre_adjust_head and slide_nodelist(pre_adjust_head) -- todo: find_tail + local adjust_tail = adjust_head and slide_nodes(adjust_head) + local pre_adjust_tail = pre_adjust_head and slide_nodes(pre_adjust_head) + + hlist.list = head + hlist.dir = hpack_dir new_dir_stack(hpack_dir) @@ -2831,205 +2787,225 @@ local function hpack(head,width,method,direction,firstline,line) -- fast version local fontexps, lastfont - local function process(current) -- called nested in disc replace + local current = head - while current do - local id = getid(current) - if id == glyph_code then - if cal_expand_ratio then - local currentfont = getfont(current) - if currentfont ~= lastfont then - fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer - lastfont = currentfont - end - if fontexps then - local expansion = fontexps[getchar(current)] - if expansion then - font_stretch = font_stretch + expansion.glyphstretch - font_shrink = font_shrink + expansion.glyphshrink - expansion_index = expansion_index + 1 - expansion_stack[expansion_index] = current - end - end - end - -- use inline - local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ? - natural = natural + wd - if ht > height then - height = ht - end - if dp > depth then - depth = dp - end - elseif id == kern_code then - local kern = getfield(current,"kern") - if kern == 0 then - -- no kern - elseif getsubtype(current) == kerning_code then -- check getfield(p,"kern") - if cal_expand_ratio then - local stretch, shrink = kern_stretch_shrink(current,kern) - font_stretch = font_stretch + stretch - font_shrink = font_shrink + shrink + while current do + local id = current.id + if id == glyph_code then + if cal_expand_ratio then + local currentfont = current.font + if currentfont ~= lastfont then + fontexps = checked_expansion[currentfont] -- a bit redundant for the par line packer + lastfont = currentfont + end + if fontexps then + local expansion = fontexps[current.char] + if expansion then + font_stretch = font_stretch + expansion.glyphstretch + font_shrink = font_shrink + expansion.glyphshrink expansion_index = expansion_index + 1 expansion_stack[expansion_index] = current end - natural = natural + kern - else - natural = natural + kern end - elseif id == disc_code then - local subtype = getsubtype(current) - if subtype ~= second_disc_code then - -- todo : local stretch, shrink = char_stretch_shrink(s) - local replace = getfield(current,"replace") - if replace then - process(replace) - end - end - elseif id == glue_code then - local spec = getfield(current,"spec") - natural = natural + getfield(spec,"width") - local op = getfield(spec,"stretch_order") - local om = getfield(spec,"shrink_order") - total_stretch[op] = total_stretch[op] + getfield(spec,"stretch") - total_shrink [om] = total_shrink [om] + getfield(spec,"shrink") - if getsubtype(current) >= leaders_code then - local leader = getleader(current) - local ht = getfield(leader,"height") - local dp = getfield(leader,"depth") - if ht > height then - height = ht - end - if dp > depth then - depth = dp + end + -- use inline if no expansion + local wd, ht, dp = glyph_width_height_depth(hpack_dir,"TLT",current) -- was TRT ? + natural = natural + wd + if ht > height then + height = ht + end + if dp > depth then + depth = dp + end + current = current.next + elseif id == kern_code then + local kern = current.kern + if kern == 0 then + -- no kern + else + if cal_expand_ratio and expand_kerns and current.subtype == kerning_code or current[a_fontkern] then -- check p.kern + local stretch, shrink = kern_stretch_shrink(current,kern) + if expand_kerns == "stretch" then + font_stretch = font_stretch + stretch + elseif expand_kerns == "shrink" then + font_shrink = font_shrink + shrink + else + font_stretch = font_stretch + stretch + font_shrink = font_shrink + shrink end + expansion_index = expansion_index + 1 + expansion_stack[expansion_index] = current end - elseif id == hlist_code or id == vlist_code then - local sh = getfield(current,"shift") - local wd, ht, dp = pack_width_height_depth(hpack_dir,getfield(current,"dir") or hpack_dir,current) -- added: or pack_dir - local hs, ds = ht - sh, dp + sh - natural = natural + wd - if hs > height then - height = hs - end - if ds > depth then - depth = ds + natural = natural + kern + end + current = current.next + elseif id == disc_code then + if current.subtype ~= second_disc_code then + -- we follow the end of line disc chain + local replace = current.replace + if replace then + disc_level = disc_level + 1 + disc_stack[disc_level] = current.next + current = replace + else + current = current.next end - elseif id == rule_code then - local wd = getfield(current,"width") - local ht = getfield(current,"height") - local dp = getfield(current,"depth") - natural = natural + wd + else + current = current.next + end + elseif id == glue_code then + local spec = current.spec + natural = natural + spec.width + local op = spec.stretch_order + local om = spec.shrink_order + total_stretch[op] = total_stretch[op] + spec.stretch + total_shrink [om] = total_shrink [om] + spec.shrink + if current.subtype >= leaders_code then + local leader = current.leader + local ht = leader.height + local dp = leader.depth if ht > height then height = ht end if dp > depth then depth = dp end - elseif id == math_code then - natural = natural + getfield(current,"surround") - elseif id == unset_code then - local wd = getfield(current,"width") - local ht = getfield(current,"height") - local dp = getfield(current,"depth") - local sh = getfield(current,"shift") - local hs = ht - sh - local ds = dp + sh - natural = natural + wd - if hs > height then - height = hs + end + current = current.next + elseif id == hlist_code or id == vlist_code then + local sh = current.shift + local wd, ht, dp = pack_width_height_depth(hpack_dir,current.dir or hpack_dir,current) -- added: or pack_dir + local hs, ds = ht - sh, dp + sh + natural = natural + wd + if hs > height then + height = hs + end + if ds > depth then + depth = ds + end + current = current.next + elseif id == rule_code then + local wd = current.width + local ht = current.height + local dp = current.depth + natural = natural + wd + if ht > height then + height = ht + end + if dp > depth then + depth = dp + end + current = current.next + elseif id == math_code then + natural = natural + current.surround + current = current.next + elseif id == unset_code then + local wd = current.width + local ht = current.height + local dp = current.depth + local sh = current.shift + local hs = ht - sh + local ds = dp + sh + natural = natural + wd + if hs > height then + height = hs + end + if ds > depth then + depth = ds + end + current = current.next + elseif id == ins_code or id == mark_code then + local prev = current.prev + local next = current.next + if adjust_tail then -- todo + if next then + next.prev = prev end - if ds > depth then - depth = ds + if prev then + prev.next = next end - elseif id == ins_code or id == mark_code then - local prev = getprev(current) - local next = getnext(current) - if adjust_tail then -- todo - if next then - setfield(next,"prev",prev) - end - if prev then - setfield(prev,"next",next) + current.prev = adjust_tail + current.next = nil + adjust_tail.next = current + adjust_tail = current + else + adjust_head = current + adjust_tail = current + current.prev = nil + current.next = nil + end + current = next + elseif id == adjust_code then + local list = current.list + if adjust_tail then + adjust_tail.next = list + adjust_tail = slide_nodes(list) + else + adjust_head = list + adjust_tail = slide_nodes(list) + end + current = current.next + elseif id == whatsit_code then + local subtype = current.subtype + if subtype == dir_code then + hpack_dir = checked_line_dir(stack,current) or hpack_dir + else + local get_dimensions = get_whatsit_dimensions[subtype] + if get_dimensions then + local wd, ht, dp = get_dimensions(current) + natural = natural + wd + if ht > height then + height = ht end - setfield(current,"prev",adjust_tail) - setfield(current,"next",nil) - adjust_setfield(tail,"next",current) - adjust_tail = current - else - adjust_head = current - adjust_tail = current - setfield(current,"prev",nil) - setfield(current,"next",nil) - end - elseif id == adjust_code then - local list = getlist(current) - if adjust_tail then - adjust_setfield(tail,"next",list) - else - adjust_head = list - end - adjust_tail = slide_nodelist(list) -- find_tail(list) - elseif id == whatsit_code then - local subtype = getsubtype(current) - if subtype == dir_code then - hpack_dir = checked_line_dir(stack,current) or hpack_dir - else - local get_dimensions = get_whatsit_dimensions[subtype] - if get_dimensions then - local wd, ht, dp = get_dimensions(current,hpack_dir) - natural = natural + wd - if ht > height then - height = ht - end - if dp > depth then - depth = dp - end + if dp > depth then + depth = dp end end - elseif id == marginkern_code then - local width = getfield(current,"width") - if cal_expand_ratio then - -- is this ok? - local glyph = getfield(current,"glyph") - local char_pw = getsubtype(current) == leftmargin_code and left_pw or right_pw - font_stretch = font_stretch - width - char_pw(glyph) - font_shrink = font_shrink - width - char_pw(glyph) - expansion_index = expansion_index + 1 - expansion_stack[expansion_index] = glyph - end - natural = natural + width end - current = getnext(current) + current = current.next + elseif id == marginkern_code then + if cal_expand_ratio then + local glyph = current.glyph + local char_pw = current.subtype == leftmargin_code and left_pw or right_pw + font_stretch = font_stretch - current.width - char_pw(glyph) + font_shrink = font_shrink - current.width - char_pw(glyph) + expansion_index = expansion_index + 1 + expansion_stack[expansion_index] = glyph + end + natural = natural + current.width + current = current.next + else + current = current.next + end + if not current and disc_level > 0 then + current = disc_stack[disc_level] + disc_level = disc_level - 1 end - end - - process(head) - if adjust_tail then adjust_tail.next = nil -- todo end if pre_adjust_tail then pre_adjust_tail.next = nil -- todo end - if method == "additional" then + if mode == "additional" then width = width + natural end - setfield(hlist,"width",width) - setfield(hlist,"height",height) - setfield(hlist,"depth",depth) + hlist.width = width + hlist.height = height + hlist.depth = depth local delta = width - natural if delta == 0 then - setfield(hlist,"glue_sign",0) - setfield(hlist,"glue_order",0) - setfield(hlist,"glue_set",0) + hlist.glue_sign = 0 + hlist.glue_order = 0 + hlist.glue_set = 0 elseif delta > 0 then -- natural width smaller than requested width local order = (total_stretch[4] ~= 0 and 4 or total_stretch[3] ~= 0 and 3) or (total_stretch[2] ~= 0 and 2 or total_stretch[1] ~= 0 and 1) or 0 +-- local correction = 0 if cal_expand_ratio and order == 0 and font_stretch > 0 then -- check sign of font_stretch font_expand_ratio = delta/font_stretch @@ -3041,38 +3017,41 @@ local function hpack(head,width,method,direction,firstline,line) -- fast version for i=1,expansion_index do local g = expansion_stack[i] local e - if getid(g) == glyph_code then - local currentfont = getfont(g) + if g.id == glyph_code then + local currentfont = g.font if currentfont ~= lastfont then fontexps = expansions[currentfont] lastfont = currentfont end - local data = fontexps[getchar(g)] + local data = fontexps[g.char] if trace_expansion then setnodecolor(g,"hz:positive") end e = font_expand_ratio * data.glyphstretch / 1000 +-- correction = correction + (e / 1000) * g.width else - local kern = getfield(g,"kern") + local kern = g.kern local stretch, shrink = kern_stretch_shrink(g,kern) e = font_expand_ratio * stretch / 1000 +-- correction = correction + (e / 1000) * kern end - setfield(g,"expansion_factor",e) + g.expansion_factor = e end end +-- delta = delta - correction local tso = total_stretch[order] if tso ~= 0 then - setfield(hlist,"glue_sign",1) - setfield(hlist,"glue_order",order) - setfield(hlist,"glue_set",delta/tso) + hlist.glue_sign = 1 + hlist.glue_order = order + hlist.glue_set = delta/tso else - setfield(hlist,"glue_sign",0) - setfield(hlist,"glue_order",order) - setfield(hlist,"glue_set",0) + hlist.glue_sign = 0 + hlist.glue_order = order + hlist.glue_set = 0 end if font_expand_ratio ~= 0 then -- todo - elseif order == 0 then -- and getlist(hlist) then + elseif order == 0 then -- and hlist.list then last_badness = calculate_badness(delta,total_stretch[0]) if last_badness > tex.hbadness then if last_badness > 100 then @@ -3086,6 +3065,7 @@ local function hpack(head,width,method,direction,firstline,line) -- fast version -- natural width larger than requested width local order = total_shrink[4] ~= 0 and 4 or total_shrink[3] ~= 0 and 3 or total_shrink[2] ~= 0 and 2 or total_shrink[1] ~= 0 and 1 or 0 +-- local correction = 0 if cal_expand_ratio and order == 0 and font_shrink > 0 then -- check sign of font_shrink font_expand_ratio = delta/font_shrink @@ -3097,47 +3077,54 @@ local function hpack(head,width,method,direction,firstline,line) -- fast version for i=1,expansion_index do local g = expansion_stack[i] local e - if getid(g) == glyph_code then - local currentfont = getfont(g) + if g.id == glyph_code then + local currentfont = g.font if currentfont ~= lastfont then fontexps = expansions[currentfont] lastfont = currentfont end - local data = fontexps[getchar(g)] + local data = fontexps[g.char] if trace_expansion then setnodecolor(g,"hz:negative") end e = font_expand_ratio * data.glyphshrink / 1000 + -- local d = (e / 1000) * 1000 + -- local eps = g.width - (1 + d / 1000000) * g.width + -- correction = correction + eps + -- e = d +-- correction = correction + (e / 1000) * g.width else - local kern = getfield(g,"kern") + local kern = g.kern local stretch, shrink = kern_stretch_shrink(g,kern) e = font_expand_ratio * shrink / 1000 +-- correction = correction + (e / 1000) * kern end - setfield(g,"expansion_factor",e) + g.expansion_factor = e end end +-- delta = delta - correction local tso = total_shrink[order] if tso ~= 0 then - setfield(hlist,"glue_sign",2) - setfield(hlist,"glue_order",order) - setfield(hlist,"glue_set",-delta/tso) + hlist.glue_sign = 2 + hlist.glue_order = order + hlist.glue_set = -delta/tso else - setfield(hlist,"glue_sign",0) - setfield(hlist,"glue_order",order) - setfield(hlist,"glue_set",0) + hlist.glue_sign = 0 + hlist.glue_order = order + hlist.glue_set = 0 end if font_expand_ratio ~= 0 then -- todo - elseif tso < -delta and order == 0 then -- and getlist(hlist) then + elseif tso < -delta and order == 0 then -- and hlist.list then last_badness = 1000000 - setfield(hlist,"glue_set",1) + hlist.glue_set = 1 local fuzz = - delta - total_shrink[0] local hfuzz = tex.hfuzz if fuzz > hfuzz or tex.hbadness < 100 then local overfullrule = tex.overfullrule if fuzz > hfuzz and overfullrule > 0 then -- weird, is always called and no rules shows up - setfield(slide_nodelist(list),"next",new_rule(overfullrule,nil,nil,hlist.dir)) -- todo: find_tail + slide_nodes(list).next = new_rule(overfullrule,nil,nil,hlist.dir) end diagnostics.overfull_hbox(hlist,line,-delta) end @@ -3148,7 +3135,7 @@ local function hpack(head,width,method,direction,firstline,line) -- fast version return hlist, last_badness end -xpack_nodes = hpack -- comment this for old fashioned expansion (we need to fix float mess) +xpack_nodes = hpack -- comment this for old fashioned expansion local function common_message(hlist,line,str) write_nl("") @@ -3186,3 +3173,20 @@ end function diagnostics.loose_hbox(hlist,line,b) common_message(hlist,line,format("Loose \\hbox (badness %i)",b)) end + +-- e = font_expand_ratio * data.glyphstretch / 1000 +-- local stretch = data.stretch +-- if e >= stretch then +-- e = stretch +-- else +-- local step = 5 +-- e = math.round(e/step) * step +-- end + +-- local shrink = - data.shrink +-- if e <= shrink then +-- e = shrink +-- else +-- local step = 5 +-- e = math.round(e/step) * step +-- end diff --git a/tex/context/base/node-met.lua b/tex/context/base/node-met.lua index d52349b4a..c85a53c8e 100644 --- a/tex/context/base/node-met.lua +++ b/tex/context/base/node-met.lua @@ -332,28 +332,6 @@ function nodes.writable_spec(n) -- not pool return spec end -function nodes.copy_spec(old,free) -- also frees - if not old then - return n_new_node("glue_spec") - else - local new = n_copy_node(old) - if free and old.writable then - free_node(old) - end - return new - end -end - -function nodes.free_spec(old) - if not old then - -- skip - elseif old.writable then - free_node(old) - else - -- skip - end -end - if gonuts then function nodes.reference(n) @@ -690,34 +668,3 @@ end nodes.keys = keys -- [id][subtype] nodes.fields = nodefields -- (n) - --- one issue solved in flush_node: --- --- case glue_spec_node: --- if (glue_ref_count(p)!=null) { --- decr(glue_ref_count(p)); --- return ; --- /* --- } else if (! valid_node(p)) { --- return ; --- */ --- /* --- } else { --- free_node(p, get_node_size(type(p), subtype(p))); --- return ; --- */ --- } --- break ; --- --- or: --- --- case glue_spec_node: --- if (glue_ref_count(p)!=null) { --- decr(glue_ref_count(p)); --- return ; --- } else if (valid_node(p)) { --- free_node(p, get_node_size(type(p), subtype(p))); --- return ; --- } else { --- break ; --- } diff --git a/tex/context/base/node-mig.lua b/tex/context/base/node-mig.lua index 41f95be45..9fc35a048 100644 --- a/tex/context/base/node-mig.lua +++ b/tex/context/base/node-mig.lua @@ -6,32 +6,15 @@ if not modules then modules = { } end modules ['node-mig'] = { license = "see context related readme files" } --- todo: insert_after - local format = string.format -local trace_migrations = false trackers.register("nodes.migrations", function(v) trace_migrations = v end) +local attributes, nodes, node = attributes, nodes, node -local report_nodes = logs.reporter("nodes","migrations") +local remove_nodes = nodes.remove -local attributes = attributes -local nodes = nodes +local nodecodes = nodes.nodecodes local tasks = nodes.tasks -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getnext = nuts.getnext -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local remove_node = nuts.remove - -local nodecodes = nodes.nodecodes local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local insert_code = nodecodes.ins @@ -39,6 +22,10 @@ local mark_code = nodecodes.mark local a_migrated = attributes.private("migrated") +local trace_migrations = false trackers.register("nodes.migrations", function(v) trace_migrations = v end) + +local report_nodes = logs.reporter("nodes","migrations") + local migrate_inserts, migrate_marks, inserts_too local t_inserts, t_marks, t_sweeps = 0, 0, 0 @@ -46,42 +33,32 @@ local t_inserts, t_marks, t_sweeps = 0, 0, 0 local function locate(head,first,last,ni,nm) local current = head while current do - local id = getid(current) + local id = current.id if id == vlist_code or id == hlist_code then - local list = getlist(current) - if list then - list, first, last, ni, nm = locate(list,first,last,ni,nm) - setfield(current,"list",list) - end - current = getnext(current) + current.list, first, last, ni, nm = locate(current.list,first,last,ni,nm) + current = current.next elseif migrate_inserts and id == insert_code then local insert - head, current, insert = remove_node(head,current) - setfield(insert,"next",nil) + head, current, insert = remove_nodes(head,current) + insert.next = nil if first then - setfield(insert,"prev",last) - setfield(last,"next",insert) + insert.prev, last.next = last, insert else - setfield(insert,"prev",nil) - first = insert + insert.prev, first = nil, insert end - last = insert - ni = ni + 1 + last, ni = insert, ni + 1 elseif migrate_marks and id == mark_code then local mark - head, current, mark = remove_node(head,current) - setfield(mark,"next",nil) + head, current, mark = remove_nodes(head,current) + mark.next = nil if first then - setfield(mark,"prev",last) - setfield(last,"next",mark) + mark.prev, last.next = last, mark else - setfield(mark,"prev",nil) - first = mark + mark.prev, first = nil, mark end - last = mark - nm = nm + 1 + last, nm = mark, nm + 1 else - current = getnext(current) + current= current.next end end return head, first, last, ni, nm @@ -93,43 +70,39 @@ function nodes.handlers.migrate(head,where) if trace_migrations then report_nodes("migration sweep %a",where) end - local current = tonut(head) + local current = head while current do - local id = getid(current) + local id = current.id -- inserts_too is a temp hack, we should only do them when it concerns -- newly placed (flushed) inserts - if id == vlist_code or id == hlist_code or (inserts_too and id == insert_code) and not getattr(current,a_migrated) then - setattr(current,a_migrated,1) + if id == vlist_code or id == hlist_code or (inserts_too and id == insert_code) and not current[a_migrated] then + current[a_migrated] = 1 t_sweeps = t_sweeps + 1 - local h = getlist(current) + local h = current.list local first, last, ni, nm while h do - local id = getid(h) + local id = h.id if id == vlist_code or id == hlist_code then h, first, last, ni, nm = locate(h,first,last,0,0) end - h = getnext(h) + h = h.next end if first then - t_inserts = t_inserts + ni - t_marks = t_marks + nm + t_inserts, t_marks = t_inserts + ni, t_marks + nm if trace_migrations and (ni > 0 or nm > 0) then report_nodes("sweep %a, container %a, %s inserts and %s marks migrated outwards during %a", t_sweeps,nodecodes[id],ni,nm,where) end - -- inserts after head, use insert_after - local n = getnext(current) + -- inserts after head + local n = current.next if n then - setfield(last,"next",n) - setfield(n,"prev",last) + last.next, n.prev = n, last end - setfield(current,"next",first) - setfield(first,"prev",current) - done = true - current = last + current.next, first.prev = first, current + done, current = true, last end end - current = getnext(next) + current = current.next end return head, done end diff --git a/tex/context/base/node-nut.lua b/tex/context/base/node-nut.lua deleted file mode 100644 index 4732b09eb..000000000 --- a/tex/context/base/node-nut.lua +++ /dev/null @@ -1,650 +0,0 @@ -if not modules then modules = { } end modules ['node-met'] = { - version = 1.001, - comment = "companion to node-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- Here starts some more experimental code that Luigi and I use in a next stage of --- exploring and testing potential speedups in the engines. This code is not meant --- for users and can change (or be removed) any moment. During the experiments I'll --- do my best to keep the code as fast as possible by using two codebases. See --- about-fast.pdf for some more info about impacts. Although key based access has --- more charm, function based is somewhat faster and has more potential for future --- speedups. - --- This next iteration is flagged direct because we avoid user data which has a price --- in allocation and metatable tagging. Although in this stage we pass numbers around --- future versions might use light user data, so never depend on what direct function --- return. Using the direct approach had some speed advantages but you loose the key --- based access. The speed gain is only measurable in cases with lots of access. For --- instance when typesettign arabic with advanced fonts, we're talking of many millions --- of function calls and there we can get a 30\% or more speedup. On average complex --- \CONTEXT\ runs the gain can be 10\% to 15\% percent. Because mixing the two models --- (here we call then nodes and nuts) is not possible you need to cast either way which --- has a penalty. Also, error messages in nuts mode are less clear and \LUATEX\ will --- often simply abort when you make mistakes of mix the models. So, development (at least --- in \CONTEXT) can be done in node mode and not in nuts mode. Only robust code will --- be turned nuts afterwards and quite likely not all code. The official \LUATEX\ api --- to nodes is userdata! --- --- Listening to 'lunatic soul' at the same time helped wrapping my mind around the mixed --- usage of both models. Just for the record: the potential of the direct approach only --- became clear after experimenting for weeks and partly adapting code. It is one of those --- (sub)projects where you afterwards wonder if it was worth the trouble, but users that --- rely on lots of complex functionality and font support will probably notice the speedup. --- --- luatex luajittex --- ------------- ----- -------------------- --------------------------------- --- name pages old new pct old new pct --- ------------- ----- -------------------- --------------------------------- --- fonts-mkiv 166 9.3 7.7/7.4 17.2 7.4 (37.5) 5.9/5.7 (55.6) 20.3 --- about 60 3.3 2.7/2.6 20.4 2.5 (39.5) 2.1 (57.0) 23.4 --- arabic-001 61 25.3 15.8 18.2 15.3 (46.7) 6.8 (54.7) 16.0 --- torture-001 300 21.4 11.4 24.2 13.9 (35.0) 6.3 (44.7) 22.2 --- --- so: --- --- - we run around 20% faster on documents of average complexity and gain more when --- dealing with scripts like arabic and such --- - luajittex benefits a bit more so a luajittex job can (in principle) now be much --- faster --- - if we reason backwards, and take luajittex as norm we get 1:2:3 on some jobs for --- luajittex direct:luatex direct:luatex normal i.e. we can be 3 times faster --- - keep in mind that these are tex/lua runs so the real gain at the lua end is much --- larger --- --- Because we can fake direct mode a little bit by using the fast getfield and setfield --- at the cost of wrapped getid and alike, we still are running quite ok. As we could gain --- some 5% with fast mode, we can sacrifice some on wrappers when we use a few fast core --- functions. This means that simulated direct mode runs font-mkiv in 9.1 seconds (we could --- get down to 8.7 seconds in fast mode) and that we can migrate slowely to direct mode. --- --- The following measurements are from 2013-07-05 after adapting some 47 files to nuts. Keep --- in mind that the old binary can fake a fast getfield and setfield but that the other --- getters are wrapped functions. The more we have, the slower it gets. --- --- fonts about arabic --- old mingw, indexed plus some functions : 8.9 3.2 20.3 --- old mingw, fake functions : 9.9 3.5 27.4 --- new mingw, node functions : 9.0 3.1 20.8 --- new mingw, indexed plus some functions : 8.6 3.1 19.6 --- new mingw, direct functions : 7.5 2.6 14.4 --- --- \starttext \dorecurse{1000}{test\page} \stoptext : --- --- luatex 560 pps --- luajittex 600 pps --- --- \setupbodyfont[pagella] --- --- \edef\zapf{\cldcontext{context(io.loaddata(resolvers.findfile("zapf.tex")))}} --- --- \starttext \dorecurse{1000}{\zapf\par} \stoptext --- --- luatex 3.9 sec / 54 pps --- luajittex 2.3 sec / 93 pps - -local nodes = nodes -local gonuts = nodes.gonuts -local direct = node.direct - -if type(direct) ~= "table" then - return -elseif gonuts then - statistics.register("running in nuts mode", function() return "yes" end) -else - statistics.register("running in nuts mode", function() return "no" end) - return -end - -local texget = tex.get - -local nodecodes = nodes.nodecodes -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist - -local nuts = nodes.nuts or { } -nodes.nuts = nuts - -nodes.is_node = direct.is_node or function() return true end -nodes.is_direct = direct.is_direct or function() return false end -nodes.is_nut = nodes.is_direct - --- casters - -local tonode = direct.tonode or function(n) return n end -local tonut = direct.todirect or function(n) return n end - -nuts.tonode = tonode -nuts.tonut = tonut - -nodes.tonode = tonode -nodes.tonut = tonut - --- getters - -nuts.getfield = direct.getfield -nuts.getnext = direct.getnext -nuts.getprev = direct.getprev -nuts.getid = direct.getid -nuts.getattr = direct.getfield -nuts.getchar = direct.getchar -nuts.getfont = direct.getfont -nuts.getsubtype = direct.getsubtype -nuts.getlist = direct.getlist -- only hlist and vlist ! -nuts.getleader = direct.getleader - --- local dgf = direct.getfield function nuts.getlist(n) return dgf(n,"list") end - --- setters - -nuts.setfield = direct.setfield -nuts.setattr = direct.setfield - -nuts.getbox = direct.getbox -nuts.setbox = direct.setbox -nuts.getskip = direct.getskip or function(s) return tonut(texget(s)) end - --- helpers - -nuts.tostring = direct.tostring -nuts.copy = direct.copy -nuts.copy_list = direct.copy_list -nuts.delete = direct.delete -nuts.dimensions = direct.dimensions -nuts.end_of_math = direct.end_of_math -nuts.flush_list = direct.flush_list -nuts.flush_node = direct.flush_node -nuts.free = direct.free -nuts.insert_after = direct.insert_after -nuts.insert_before = direct.insert_before -nuts.hpack = direct.hpack -nuts.new = direct.new -nuts.tail = direct.tail -nuts.traverse = direct.traverse -nuts.traverse_id = direct.traverse_id -nuts.slide = direct.slide -nuts.writable_spec = direct.writable_spec -nuts.vpack = direct.vpack -nuts.is_node = direct.is_node -nuts.is_direct = direct.is_direct -nuts.is_nut = direct.is_direct -nuts.first_glyph = direct.first_glyph -nuts.first_character = direct.first_character -nuts.has_glyph = direct.has_glyph or direct.first_glyph - -nuts.current_attr = direct.current_attr -nuts.do_ligature_n = direct.do_ligature_n -nuts.has_field = direct.has_field -nuts.last_node = direct.last_node -nuts.usedlist = direct.usedlist -nuts.protrusion_skippable = direct.protrusion_skippable -nuts.write = direct.write - -nuts.has_attribute = direct.has_attribute -nuts.set_attribute = direct.set_attribute -nuts.unset_attribute = direct.unset_attribute - -nuts.protect_glyphs = direct.protect_glyphs -nuts.unprotect_glyphs = direct.unprotect_glyphs - --- placeholders - -if not direct.kerning then - - local n_kerning = node.kerning - - function nuts.kerning(head) - return tonode(n_kerning(tonut(head))) - end - -end - -if not direct.ligaturing then - - local n_ligaturing = node.ligaturing - - function nuts.ligaturing(head) - return tonode(n_ligaturing(tonut(head))) - end - -end - -if not direct.mlist_to_hlist then - - local n_mlist_to_hlist = node.mlist_to_hlist - - function nuts.mlist_to_hlist(head) - return tonode(n_mlist_to_hlist(tonut(head))) - end - -end - --- - -local d_remove_node = direct.remove -local d_free_node = direct.free -local d_getfield = direct.getfield -local d_setfield = direct.setfield -local d_getnext = direct.getnext -local d_getprev = direct.getprev -local d_getid = direct.getid -local d_getlist = direct.getlist -local d_find_tail = direct.tail -local d_insert_after = direct.insert_after -local d_insert_before = direct.insert_before -local d_slide = direct.slide -local d_copy_node = direct.copy -local d_traverse = direct.traverse - -local function remove(head,current,free_too) - local t = current - head, current = d_remove_node(head,current) - if not t then - -- forget about it - elseif free_too then - d_free_node(t) - t = nil - else - d_setfield(t,"next",nil) -- not that much needed (slows down unless we check the source on this) - d_setfield(t,"prev",nil) -- not that much needed (slows down unless we check the source on this) - end - return head, current, t -end - --- bad: we can have prev's being glue_spec - --- local function remove(head,current,free_too) -- d_remove_node does a slide which can fail --- local prev = d_getprev(current) -- weird --- local next = d_getnext(current) --- if next then --- -- print("!!!!!!!! prev is gluespec", --- -- nodes.nodecodes[d_getid(current)], --- -- nodes.nodecodes[d_getid(next)], --- -- nodes.nodecodes[d_getid(prev)]) --- d_setfield(prev,"next",next) --- d_setfield(next,"prev",prev) --- else --- d_setfield(prev,"next",nil) --- end --- if free_too then --- d_free_node(current) --- current = nil --- else --- d_setfield(current,"next",nil) -- use this fact ! --- d_setfield(current,"prev",nil) -- use this fact ! --- end --- if head == current then --- return next, next, current --- else --- return head, next, current --- end --- end - -nuts.remove = remove - -function nuts.delete(head,current) - return remove(head,current,true) -end - -function nuts.replace(head,current,new) -- no head returned if false - if not new then - head, current, new = false, head, current - end - local prev = d_getprev(current) - local next = d_getnext(current) - if next then - d_setfield(new,"next",next) - d_setfield(next,"prev",new) - end - if prev then - d_setfield(new,"prev",prev) - d_setfield(prev,"next",new) - end - if head then - if head == current then - head = new - end - d_free_node(current) - return head, new - else - d_free_node(current) - return new - end -end - -local function count(stack,flat) - local n = 0 - while stack do - local id = d_getid(stack) - if not flat and id == hlist_code or id == vlist_code then - local list = d_getlist(stack) - if list then - n = n + 1 + count(list) -- self counts too - else - n = n + 1 - end - else - n = n + 1 - end - stack = d_getnext(stack) - end - return n -end - -nuts.count = count - -function nuts.append(head,current,...) - for i=1,select("#",...) do - head, current = d_insert_after(head,current,(select(i,...))) - end - return head, current -end - -function nuts.prepend(head,current,...) - for i=1,select("#",...) do - head, current = d_insert_before(head,current,(select(i,...))) - end - return head, current -end - -function nuts.linked(...) - local head, last - for i=1,select("#",...) do - local next = select(i,...) - if next then - if head then - d_setfield(last,"next",next) - d_setfield(next,"prev",last) - else - head = next - end - last = d_find_tail(next) -- we could skip the last one - end - end - return head -end - -function nuts.concat(list) -- consider tail instead of slide - local head, tail - for i=1,#list do - local li = list[i] - if li then - if head then - d_setfield(tail,"next",li) - d_setfield(li,"prev",tail) - else - head = li - end - tail = d_slide(li) - end - end - return head, tail -end - -function nuts.writable_spec(n) -- not pool - local spec = d_getfield(n,"spec") - if not spec then - spec = d_copy_node(glue_spec) - d_setfield(n,"spec",spec) - elseif not d_getfield(spec,"writable") then - spec = d_copy_node(spec) - d_setfield(n,"spec",spec) - end - return spec -end - -function nuts.reference(n) - return n or "<none>" -end - --- quick and dirty tracing of nuts - --- for k, v in next, nuts do --- if string.find(k,"box") then --- nuts[k] = function(...) print(k,...) return v(...) end --- end --- end - -function nodes.vianuts (f) return function(n,...) return tonode(f(tonut (n),...)) end end -function nodes.vianodes(f) return function(n,...) return tonut (f(tonode(n),...)) end end - -nuts.vianuts = nodes.vianuts -nuts.vianodes = nodes.vianodes - --- for k, v in next, nuts do --- if type(v) == "function" then --- if not string.find(k,"^[sg]et") and not string.find(k,"^to") then --- local f = v --- nuts[k] = function(...) print("d",k,...) return f(...) end --- end --- end --- end - --- for k, v in next, nodes do --- if type(v) == "function" then --- if not string.find(k,"^[sg]et") and not string.find(k,"^to") then --- local f = v --- nodes[k] = function(...) print("n",k,...) return f(...) end --- end --- end --- end - --- function nodes.insert_before(h,c,n) --- if c then --- if c == h then --- n_setfield(n,"next",h) --- n_setfield(n,"prev",nil) --- n_setfield(h,"prev",n) --- else --- local cp = n_getprev(c) --- n_setfield(n,"next",c) --- n_setfield(n,"prev",cp) --- if cp then --- n_setfield(cp,"next",n) --- end --- n_setfield(c,"prev",n) --- return h, n --- end --- end --- return n, n --- end - --- function nodes.insert_after(h,c,n) --- if c then --- local cn = n_getnext(c) --- if cn then --- n_setfield(n,"next",cn) --- n_setfield(cn,"prev",n) --- else --- n_setfield(n,"next",nil) --- end --- n_setfield(c,"next",n) --- n_setfield(n,"prev",c) --- return h, n --- end --- return n, n --- end - -function nodes.insert_list_after(h,c,n) - local t = n_tail(n) - if c then - local cn = n_getnext(c) - if cn then - n_setfield(t,"next",cn) - n_setfield(cn,"prev",t) - else - n_setfield(t,"next",nil) - end - n_setfield(c,"next",n) - n_setfield(n,"prev",c) - return h, n - end - return n, t -end - --- function nuts.insert_before(h,c,n) --- if c then --- if c == h then --- d_setfield(n,"next",h) --- d_setfield(n,"prev",nil) --- d_setfield(h,"prev",n) --- else --- local cp = d_getprev(c) --- d_setfield(n,"next",c) --- d_setfield(n,"prev",cp) --- if cp then --- d_setfield(cp,"next",n) --- end --- d_setfield(c,"prev",n) --- return h, n --- end --- end --- return n, n --- end - --- function nuts.insert_after(h,c,n) --- if c then --- local cn = d_getnext(c) --- if cn then --- d_setfield(n,"next",cn) --- d_setfield(cn,"prev",n) --- else --- d_setfield(n,"next",nil) --- end --- d_setfield(c,"next",n) --- d_setfield(n,"prev",c) --- return h, n --- end --- return n, n --- end - -function nuts.insert_list_after(h,c,n) - local t = d_tail(n) - if c then - local cn = d_getnext(c) - if cn then - d_setfield(t,"next",cn) - d_setfield(cn,"prev",t) - else - d_setfield(t,"next",nil) - end - d_setfield(c,"next",n) - d_setfield(n,"prev",c) - return h, n - end - return n, t -end - --- test code only - --- collectranges and mix - -local report = logs.reporter("sliding") - -local function message(detail,head,current,previous) - report("error: %s, current: %s:%s, previous: %s:%s, list: %s, text: %s", - detail, - nodecodes[d_getid(current)], - current, - nodecodes[d_getid(previous)], - previous, - nodes.idstostring(head), - nodes.listtoutf(head) - ) - utilities.debugger.showtraceback(report) -end - -local function warn() - report() - report("warning: the slide tracer is enabled") - report() - warn = false -end - -local function tracedslide(head) - if head then - if warn then - warn() - end - local next = d_getnext(head) - if next then - local prev = head - for n in d_traverse(next) do - local p = d_getprev(n) - if not p then - message("unset",head,n,prev) - -- break - elseif p ~= prev then - message("wrong",head,n,prev) - -- break - end - prev = n - end - end - return d_slide(head) - end -end - -local function nestedtracedslide(head,level) -- no sliding ! - if head then - if warn then - warn() - end - local id = d_getid(head) - local next = d_getnext(head) - if next then - report("%whead:%s",level or 0,nodecodes[id]) - local prev = head - for n in d_traverse(next) do - local p = d_getprev(n) - if not p then - message("unset",head,n,prev) - -- break - elseif p ~= prev then - message("wrong",head,n,prev) - -- break - end - prev = n - local id = d_getid(n) - if id == hlist_code or id == vlist_code then - nestedtracedslide(d_getlist(n),(level or 0) + 1) - end - end - elseif id == hlist_code or id == vlist_code then - report("%wlist:%s",level or 0,nodecodes[id]) - nestedtracedslide(d_getlist(head),(level or 0) + 1) - end - -- return d_slide(head) - end -end - -local function untracedslide(head) - if head then - if warn then - warn() - end - local next = d_getnext(head) - if next then - local prev = head - for n in d_traverse(next) do - local p = d_getprev(n) - if not p then - return "unset", d_getid(n) - elseif p ~= prev then - return "wrong", d_getid(n) - end - prev = n - end - end - return d_slide(head) - end -end - -nuts.tracedslide = tracedslide -nuts.untracedslide = untracedslide -nuts.nestedtracedslide = nestedtracedslide - --- nuts.slide = tracedslide diff --git a/tex/context/base/node-pro.lua b/tex/context/base/node-pro.lua index 2cc00601c..aa6692d7b 100644 --- a/tex/context/base/node-pro.lua +++ b/tex/context/base/node-pro.lua @@ -13,15 +13,15 @@ local trace_callbacks = false trackers.register("nodes.callbacks", function(v) local report_nodes = logs.reporter("nodes","processors") -local nodes = nodes +local nodes, node = nodes, node local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local tasks = nodes.tasks -local nuts = nodes.nuts -local first_glyph = nodes.first_glyph -local has_glyph = nodes.has_glyph +local free_node = node.free +local first_glyph = node.first_glyph or node.first_character +local has_attribute = node.has_attribute nodes.processors = nodes.processors or { } local processors = nodes.processors @@ -31,53 +31,43 @@ local processors = nodes.processors local actions = tasks.actions("processors") -do +local n = 0 - local tonut = nuts.tonut - local getid = nuts.getid - local getchar = nuts.getchar - local getnext = nuts.getnext - - local n = 0 - - local function reconstruct(head) -- we probably have a better one - local t, n, h = { }, 0, tonut(head) - while h do - n = n + 1 - local id = getid(h) - if id == glyph_code then -- todo: disc etc - t[n] = utfchar(getchar(h)) - else - t[n] = "[]" - end - h = getnext(h) - end - return concat(t) - end - - local function tracer(what,state,head,groupcode,before,after,show) - if not groupcode then - groupcode = "unknown" - elseif groupcode == "" then - groupcode = "mvl" - end +local function reconstruct(head) -- we probably have a better one + local t, n, h = { }, 0, head + while h do n = n + 1 - if show then - report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s, stream: %s",what,n,state,groupcode,before,after,reconstruct(head)) + local id = h.id + if id == glyph_code then -- todo: disc etc + t[n] = utfchar(h.char) else - report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s",what,n,state,groupcode,before,after) + t[n] = "[]" end + h = h.next end + return concat(t) +end - processors.tracer = tracer - +local function tracer(what,state,head,groupcode,before,after,show) + if not groupcode then + groupcode = "unknown" + elseif groupcode == "" then + groupcode = "mvl" + end + n = n + 1 + if show then + report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s, stream: %s",what,n,state,groupcode,before,after,reconstruct(head)) + else + report_nodes("%s: location %a, state %a, group %a, # before %a, # after %s",what,n,state,groupcode,before,after) + end end +processors.tracer = tracer + processors.enabled = true -- this will become a proper state (like trackers) function processors.pre_linebreak_filter(head,groupcode) -- ,size,packtype,direction - -- local first, found = first_glyph(head) -- they really need to be glyphs - local found = has_glyph(head) + local first, found = first_glyph(head) -- they really need to be glyphs if found then if trace_callbacks then local before = nodes.count(head,true) @@ -104,8 +94,10 @@ local enabled = true function processors.hpack_filter(head,groupcode,size,packtype,direction) if enabled then - -- local first, found = first_glyph(head) -- they really need to be glyphs - local found = has_glyph(head) + -- if not head.next and head.id ~= glyph_code then -- happens often but not faster + -- return true + -- end + local first, found = first_glyph(head) -- they really need to be glyphs if found then if trace_callbacks then local before = nodes.count(head,true) @@ -129,36 +121,15 @@ function processors.hpack_filter(head,groupcode,size,packtype,direction) return true end -do - - local setfield = nodes.setfield - local hpack = nodes.hpack - - function nodes.fasthpack(...) -- todo: pass explicit arguments - enabled = false - local hp, b = hpack(...) - setfield(hp,"prev",nil) - setfield(hp,"next",nil) - enabled = true - return hp, b - end - -end - -do - - local setfield = nuts.setfield - local hpack = nuts.hpack - - function nuts.fasthpack(...) -- todo: pass explicit arguments - enabled = false - local hp, b = hpack(...) - setfield(hp,"prev",nil) - setfield(hp,"next",nil) - enabled = true - return hp, b - end +local hpack = node.hpack +function nodes.fasthpack(...) -- todo: pass explicit arguments + enabled = false + local hp, b = hpack(...) + hp.prev = nil + hp.next = nil + enabled = true + return hp, b end callbacks.register('pre_linebreak_filter', processors.pre_linebreak_filter, "all kind of horizontal manipulations (before par break)") diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua index 7cfbde849..aa864fb1c 100644 --- a/tex/context/base/node-ref.lua +++ b/tex/context/base/node-ref.lua @@ -21,6 +21,7 @@ local attributes, nodes, node = attributes, nodes, node local allocate = utilities.storage.allocate, utilities.storage.mark local mark = utilities.storage.allocate, utilities.storage.mark + local nodeinjections = backends.nodeinjections local codeinjections = backends.codeinjections @@ -32,6 +33,9 @@ local colors = attributes.colors local references = structures.references local tasks = nodes.tasks +local hpack_list = node.hpack +local list_dimensions = node.dimensions + local trace_backend = false trackers.register("nodes.backend", function(v) trace_backend = v end) local trace_references = false trackers.register("nodes.references", function(v) trace_references = v end) local trace_destinations = false trackers.register("nodes.destinations", function(v) trace_destinations = v end) @@ -40,27 +44,6 @@ local report_reference = logs.reporter("backend","references") local report_destination = logs.reporter("backend","destinations") local report_area = logs.reporter("backend","areas") -local nuts = nodes.nuts -local nodepool = nuts.pool - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr -local setattr = nuts.setattr -local getsubtype = nuts.getsubtype - -local hpack_list = nuts.hpack -local list_dimensions = nuts.dimensions -local traverse = nuts.traverse -local find_node_tail = nuts.tail - local nodecodes = nodes.nodecodes local skipcodes = nodes.skipcodes local whatcodes = nodes.whatcodes @@ -80,18 +63,21 @@ local dir_code = whatcodes.dir local line_code = listcodes.line -local new_rule = nodepool.rule +local nodepool = nodes.pool + local new_kern = nodepool.kern +local traverse = node.traverse +local find_node_tail = node.tail or node.slide local tosequence = nodes.tosequence -- local function dimensions(parent,start,stop) --- stop = stop and getnext(stop) +-- stop = stop and stop.next -- if parent then -- if stop then --- return list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),start,stop) +-- return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop) -- else --- return list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign",getfield(parent,"glue_order"),start) +-- return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start) -- end -- else -- if stop then @@ -106,9 +92,9 @@ local tosequence = nodes.tosequence local function dimensions(parent,start,stop) if parent then - return list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),start,stop and getnext(stop)) + return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop and stop.next) else - return list_dimensions(start,stop and getnext(stop)) + return list_dimensions(start,stop and stop.next) end end @@ -125,25 +111,25 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t if trace_backend then report_area("head: %04i %s %s %s => w=%p, h=%p, d=%p, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved) end - setfield(result,"next",first) - setfield(first,"prev",result) + result.next = first + first.prev = result return result, last else if trace_backend then report_area("middle: %04i %s %s => w=%p, h=%p, d=%p, c=%s",reference,pardir or "---",txtdir or "----",tosequence(first,last,true),width,height,depth,resolved) end - local prev = getprev(first) + local prev = first.prev if prev then - setfield(result,"next",first) - setfield(result,"prev",prev) - setfield(prev,"next",result) - setfield(first,"prev",result) + result.next = first + result.prev = prev + prev.next = result + first.prev = result else - setfield(result,"next",first) - setfield(first,"prev",result) + result.next = first + first.prev = result end - if first == getnext(head) then - setfield(head,"next",result) -- hm, weird + if first == head.next then + head.next = result -- hm, weird end return head, last end @@ -153,9 +139,9 @@ local function inject_range(head,first,last,reference,make,stack,parent,pardir,t end local function inject_list(id,current,reference,make,stack,pardir,txtdir) - local width, height, depth, correction = getfield(current,"width"), getfield(current,"height"), getfield(current,"depth"), 0 + local width, height, depth, correction = current.width, current.height, current.depth, 0 local moveright = false - local first = getlist(current) + local first = current.list if id == hlist_code then -- box_code line_code -- can be either an explicit hbox or a line and there is no way -- to recognize this; anyway only if ht/dp (then inline) @@ -163,17 +149,17 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir) if first then if sr and sr[2] then local last = find_node_tail(first) - if getid(last) == glue_code and getsubtype(last) == rightskip_code then - local prev = getprev(last) - moveright = getid(first) == glue_code and getsubtype(first) == leftskip_code - if prev and getid(prev) == glue_code and getsubtype(prev) == parfillskip_code then - width = dimensions(current,first,getprev(prev)) -- maybe not current as we already take care of it + if last.id == glue_code and last.subtype == rightskip_code then + local prev = last.prev + moveright = first.id == glue_code and first.subtype == leftskip_code + if prev and prev.id == glue_code and prev.subtype == parfillskip_code then + width = dimensions(current,first,prev.prev) -- maybe not current as we already take care of it else - if moveright and getfield(first,"writable") then - width = width - getfield(getfield(first,"spec"),"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign") + if moveright and first.writable then + width = width - first.spec.stretch*current.glue_set * current.glue_sign end - if getfield(last,"writable") then - width = width - getfield(getfield(last,"spec"),"stretch") * getfield(current,"glue_set") * getfield(current,"glue_sign") + if last.writable then + width = width - last.spec.stretch*current.glue_set * current.glue_sign end end end @@ -198,21 +184,19 @@ local function inject_list(id,current,reference,make,stack,pardir,txtdir) report_area("box: %04i %s %s: w=%p, h=%p, d=%p, c=%s",reference,pardir or "---",txtdir or "----",width,height,depth,resolved) end if not first then - setfield(current,"list",result) + current.list = result elseif moveright then -- brr no prevs done -- result after first - local n = getnext(first) - setfield(result,"next",n) - setfield(first,"next",result) - setfield(result,"prev",first) - if n then - setfield(n,"prev",result) - end + local n = first.next + result.next = n + first.next = result + result.prev = first + if n then n.prev = result end else -- first after result - setfield(result,"next",first) - setfield(first,"prev",result) - setfield(current,"list",result) + result.next = first + first.prev = result + current.list = result end end end @@ -225,9 +209,9 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx pardir = pardir or "===" txtdir = txtdir or "===" while current do - local id = getid(current) + local id = current.id if id == hlist_code or id == vlist_code then - local r = getattr(current,attribute) + local r = current[attribute] -- somehow reference is true so the following fails (second one not done) in -- test \goto{test}[page(2)] test \gotobox{test}[page(2)] -- so let's wait till this fails again @@ -238,33 +222,32 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx if r then done[r] = (done[r] or 0) + 1 end - local list = getlist(current) + local list = current.list if list then - local h, ok - h, ok , pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) - setfield(current,"list",h) + local _ + current.list, _, pardir, txtdir = inject_areas(list,attribute,make,stack,done,r or skip or 0,current,pardir,txtdir) end if r then done[r] = done[r] - 1 end elseif id == whatsit_code then - local subtype = getsubtype(current) + local subtype = current.subtype if subtype == localpar_code then - pardir = getfield(current,"dir") + pardir = current.dir elseif subtype == dir_code then - txtdir = getfield(current,"dir") + txtdir = current.dir end - elseif id == glue_code and getsubtype(current) == leftskip_code then -- any glue at the left? + elseif id == glue_code and current.subtype == leftskip_code then -- any glue at the left? -- else - local r = getattr(current,attribute) + local r = current[attribute] if not r then -- just go on, can be kerns elseif not reference then reference, first, last, firstdir = r, current, current, txtdir elseif r == reference then last = current - elseif (done[reference] or 0) == 0 then -- or id == glue_code and getsubtype(current) == right_skip_code + elseif (done[reference] or 0) == 0 then -- or id == glue_code and current.subtype == right_skip_code if not skip or r > skip then -- maybe no > test head, current = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) reference, first, last, firstdir = nil, nil, nil, nil @@ -273,7 +256,7 @@ local function inject_areas(head,attribute,make,stack,done,skip,parent,pardir,tx reference, first, last, firstdir = r, current, current, txtdir end end - current = getnext(current) + current = current.next end if reference and (done[reference] or 0) == 0 then head = inject_range(head,first,last,reference,make,stack,parent,pardir,firstdir) @@ -288,32 +271,32 @@ local function inject_area(head,attribute,make,stack,done,parent,pardir,txtdir) txtdir = txtdir or "===" local current = head while current do - local id = getid(current) + local id = current.id if id == hlist_code or id == vlist_code then - local r = getattr(current,attribute) + local r = current[attribute] if r and not done[r] then done[r] = true inject_list(id,current,r,make,stack,pardir,txtdir) end - local list = getlist(current) + local list = current.list if list then - setfield(current,"list",inject_area(list,attribute,make,stack,done,current,pardir,txtdir)) + current.list = inject_area(list,attribute,make,stack,done,current,pardir,txtdir) end elseif id == whatsit_code then - local subtype = getsubtype(current) + local subtype = current.subtype if subtype == localpar_code then - pardir = getfield(current,"dir") + pardir = current.dir elseif subtype == dir_code then - txtdir = getfield(current,"dir") + txtdir = current.dir end else - local r = getattr(current,attribute) + local r = current[attribute] if r and not done[r] then done[r] = true head, current = inject_range(head,current,current,r,make,stack,parent,pardir,txtdir) end end - current = getnext(current) + current = current.next end end return head, true @@ -321,6 +304,12 @@ end -- tracing +local nodepool = nodes.pool + +local new_rule = nodepool.rule +local new_kern = nodepool.kern + +local set_attribute = node.set_attribute local register_color = colors.register local a_color = attributes.private('color') @@ -357,15 +346,15 @@ local function colorize(width,height,depth,n,reference,what) height = 65536/2 depth = height end - local rule = new_rule(width,height,depth) -- todo: use tracer rule - setattr(rule,a_colormodel,1) -- gray color model - setattr(rule,a_color,u_color) - setattr(rule,a_transparency,u_transparency) + local rule = new_rule(width,height,depth) + rule[a_colormodel] = 1 -- gray color model + rule[a_color] = u_color + rule[a_transparency] = u_transparency if width < 0 then local kern = new_kern(width) - setfield(rule,"width",-width) - setfield(kern,"next",rule) - setfield(rule,"prev",kern) + rule.width = -width + kern.next = rule + rule.prev = kern return kern else return rule @@ -374,6 +363,9 @@ end -- references: +local nodepool = nodes.pool +local new_kern = nodepool.kern + local texsetattribute = tex.setattribute local texsetcount = tex.setcount @@ -418,25 +410,22 @@ local function makereference(width,height,depth,reference) end local annot = nodeinjections.reference(width,height,depth,set) if annot then -annot = tonut(annot) nofreferences = nofreferences + 1 local result, current if trace_references then local step = 65536 result = hpack_list(colorize(width,height-step,depth-step,2,reference,"reference")) -- step subtracted so that we can see seperate links - setfield(result,"width",0) + result.width = 0 current = result end if current then - setfield(current,"next",annot) + current.next = annot else result = annot end references.registerpage(n) result = hpack_list(result,0) - setfield(result,"width",0) - setfield(result,"height",0) - setfield(result,"depth",0) + result.width, result.height, result.depth = 0, 0, 0 if cleanupreferences then stack[reference] = nil end return result, resolved elseif trace_references then @@ -447,19 +436,9 @@ annot = tonut(annot) end end --- function nodes.references.handler(head) --- if topofstack > 0 then --- return inject_areas(head,attribute,makereference,stack,done) --- else --- return head, false --- end --- end - function nodes.references.handler(head) if topofstack > 0 then - head = tonut(head) - local head, done = inject_areas(head,attribute,makereference,stack,done) - return tonode(head), done + return inject_areas(head,attribute,makereference,stack,done) else return head, false end @@ -505,12 +484,12 @@ local function makedestination(width,height,depth,reference) end for n=1,#name do local rule = hpack_list(colorize(width,height,depth,3,reference,"destination")) - setfield(rule,"width",0) + rule.width = 0 if not result then result, current = rule, rule else - setfield(current,"next",rule) - setfield(rule,"prev",current) + current.next = rule + rule.prev = current current = rule end width, height = width - step, height - step @@ -520,12 +499,12 @@ local function makedestination(width,height,depth,reference) for n=1,#name do local annot = nodeinjections.destination(width,height,depth,name[n],view) if annot then -annot = tonut(annot) -- obsolete soon + -- probably duplicate if not result then result = annot else - setfield(current,"next",annot) - setfield(annot,"prev",current) + current.next = annot + annot.prev = current end current = find_node_tail(annot) end @@ -533,9 +512,7 @@ annot = tonut(annot) -- obsolete soon if result then -- some internal error result = hpack_list(result,0) - setfield(result,"width",0) - setfield(result,"height",0) - setfield(result,"depth",0) + result.width, result.height, result.depth = 0, 0, 0 end if cleanupdestinations then stack[reference] = nil end return result, resolved @@ -544,25 +521,14 @@ annot = tonut(annot) -- obsolete soon end end --- function nodes.destinations.handler(head) --- if topofstack > 0 then --- return inject_area(head,attribute,makedestination,stack,done) -- singular --- else --- return head, false --- end --- end - function nodes.destinations.handler(head) if topofstack > 0 then - head = tonut(head) - local head, done = inject_areas(head,attribute,makedestination,stack,done) - return tonode(head), done + return inject_area(head,attribute,makedestination,stack,done) -- singular else return head, false end end - -- will move function references.mark(reference,h,d,view) diff --git a/tex/context/base/node-res.lua b/tex/context/base/node-res.lua index 968283745..ca9d67f91 100644 --- a/tex/context/base/node-res.lua +++ b/tex/context/base/node-res.lua @@ -18,8 +18,13 @@ local report_nodes = logs.reporter("nodes","housekeeping") local nodes, node = nodes, node +local copy_node = node.copy +local free_node = node.free +local free_list = node.flush_list +local new_node = node.new + nodes.pool = nodes.pool or { } -local nodepool = nodes.pool +local pool = nodes.pool local whatsitcodes = nodes.whatsitcodes local skipcodes = nodes.skipcodes @@ -30,453 +35,400 @@ local glyph_code = nodecodes.glyph local allocate = utilities.storage.allocate +local texgetbox = tex.getbox local texgetcount = tex.getcount local reserved, nofreserved = { }, 0 --- user nodes +local function register_node(n) + nofreserved = nofreserved + 1 + reserved[nofreserved] = n + return n +end -local userids = allocate() -local lastid = 0 +pool.register = register_node -setmetatable(userids, { - __index = function(t,k) - if type(k) == "string" then - lastid = lastid + 1 - rawset(userids,lastid,k) - rawset(userids,k,lastid) - return lastid - else - rawset(userids,k,k) - return k - end - end, - __call = function(t,k) - return t[k] +function pool.cleanup(nofboxes) -- todo + if nodes.tracers.steppers then -- to be resolved + nodes.tracers.steppers.reset() -- todo: make a registration subsystem end -} ) - --- nuts overload - -local nuts = nodes.nuts -local nutpool = { } -nuts.pool = nutpool - -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getbox = nuts.getbox -local getfield = nuts.getfield -local setfield = nuts.setfield -local getid = nuts.getid - -local copy_nut = nuts.copy -local new_nut = nuts.new -local free_nut = nuts.free - --- at some point we could have a dual set (the overhead of tonut is not much larger than --- metatable associations at the lua/c end esp if we also take assignments into account - --- table.setmetatableindex(nodepool,function(t,k,v) --- -- report_nodes("defining nodepool[%s] instance",k) --- local f = nutpool[k] --- local v = function(...) --- return tonode(f(...)) --- end --- t[k] = v --- return v --- end) --- --- -- we delay one step because that permits us a forward reference --- -- e.g. in pdfsetmatrix - -table.setmetatableindex(nodepool,function(t,k,v) - -- report_nodes("defining nodepool[%s] instance",k) - local v = function(...) - local f = nutpool[k] - local v = function(...) - return tonode(f(...)) + local nl, nr = 0, nofreserved + for i=1,nofreserved do + local ri = reserved[i] + -- if not (ri.id == glue_spec and not ri.is_writable) then + free_node(reserved[i]) + -- end + end + if nofboxes then + for i=0,nofboxes do + local l = texgetbox(i) + if l then + free_node(l) -- also list ? + nl = nl + 1 + end end - t[k] = v - return v(...) end - t[k] = v - return v -end) - -local function register_nut(n) - nofreserved = nofreserved + 1 - reserved[nofreserved] = n - return n + reserved = { } + nofreserved = 0 + return nr, nl, nofboxes -- can be nil end -local function register_node(n) - nofreserved = nofreserved + 1 - if type(n) == "number" then -- isnut(n) - reserved[nofreserved] = n - else - reserved[nofreserved] = tonut(n) +function pool.usage() + local t = { } + for n, tag in gmatch(status.node_mem_usage,"(%d+) ([a-z_]+)") do + t[tag] = n end - return n + return t end -nodepool.userids = userids -nodepool.register = register_node - -nutpool.userids = userids -nutpool.register = register_node -- could be register_nut - --- so far - -local disc = register_nut(new_nut("disc")) -local kern = register_nut(new_nut("kern",kerncodes.userkern)) -local fontkern = register_nut(new_nut("kern",kerncodes.fontkern)) -local penalty = register_nut(new_nut("penalty")) -local glue = register_nut(new_nut("glue")) -- glue.spec = nil -local glue_spec = register_nut(new_nut("glue_spec")) -local glyph = register_nut(new_nut("glyph",0)) -local textdir = register_nut(new_nut("whatsit",whatsitcodes.dir)) -local latelua = register_nut(new_nut("whatsit",whatsitcodes.latelua)) -local special = register_nut(new_nut("whatsit",whatsitcodes.special)) -local user_n = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_n,"type",100) -- 44 -local user_l = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_l,"type",110) -- 44 -local user_s = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_s,"type",115) -- 44 -local user_t = register_nut(new_nut("whatsit",whatsitcodes.userdefined)) setfield(user_t,"type",116) -- 44 -local left_margin_kern = register_nut(new_nut("margin_kern",0)) -local right_margin_kern = register_nut(new_nut("margin_kern",1)) -local lineskip = register_nut(new_nut("glue",skipcodes.lineskip)) -local baselineskip = register_nut(new_nut("glue",skipcodes.baselineskip)) -local leftskip = register_nut(new_nut("glue",skipcodes.leftskip)) -local rightskip = register_nut(new_nut("glue",skipcodes.rightskip)) -local temp = register_nut(new_nut("temp",0)) -local noad = register_nut(new_nut("noad")) +local disc = register_node(new_node("disc")) +local kern = register_node(new_node("kern",kerncodes.userkern)) +local fontkern = register_node(new_node("kern",kerncodes.fontkern)) +local penalty = register_node(new_node("penalty")) +local glue = register_node(new_node("glue")) -- glue.spec = nil +local glue_spec = register_node(new_node("glue_spec")) +local glyph = register_node(new_node("glyph",0)) +local textdir = register_node(new_node("whatsit",whatsitcodes.dir)) +local latelua = register_node(new_node("whatsit",whatsitcodes.latelua)) +local special = register_node(new_node("whatsit",whatsitcodes.special)) +local user_n = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_n.type = 100 -- 44 +local user_l = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_l.type = 110 -- 44 +local user_s = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_s.type = 115 -- 44 +local user_t = register_node(new_node("whatsit",whatsitcodes.userdefined)) user_t.type = 116 -- 44 +local left_margin_kern = register_node(new_node("margin_kern",0)) +local right_margin_kern = register_node(new_node("margin_kern",1)) +local lineskip = register_node(new_node("glue",skipcodes.lineskip)) +local baselineskip = register_node(new_node("glue",skipcodes.baselineskip)) +local leftskip = register_node(new_node("glue",skipcodes.leftskip)) +local rightskip = register_node(new_node("glue",skipcodes.rightskip)) +local temp = register_node(new_node("temp",0)) +local noad = register_node(new_node("noad")) -- the dir field needs to be set otherwise crash: -local rule = register_nut(new_nut("rule")) setfield(rule, "dir","TLT") -local hlist = register_nut(new_nut("hlist")) setfield(hlist,"dir","TLT") -local vlist = register_nut(new_nut("vlist")) setfield(vlist,"dir","TLT") - -function nutpool.zeroglue(n) - local s = getfield(n,"spec") - return - getfield(s,"width") == 0 and - getfield(s,"stretch") == 0 and - getfield(s,"shrink") == 0 and - getfield(s,"stretch_order") == 0 and - getfield(s,"shrink_order") == 0 -end - -function nutpool.glyph(fnt,chr) - local n = copy_nut(glyph) - if fnt then setfield(n,"font",fnt) end - if chr then setfield(n,"char",chr) end +local rule = register_node(new_node("rule")) rule .dir = "TLT" +local hlist = register_node(new_node("hlist")) hlist.dir = "TLT" +local vlist = register_node(new_node("vlist")) vlist.dir = "TLT" + +function pool.zeroglue(n) + local s = n.spec + return not writable or ( + s.width == 0 + and s.stretch == 0 + and s.shrink == 0 + and s.stretch_order == 0 + and s.shrink_order == 0 + ) +end + +function pool.glyph(fnt,chr) + local n = copy_node(glyph) + if fnt then n.font = fnt end + if chr then n.char = chr end return n end -function nutpool.penalty(p) - local n = copy_nut(penalty) - setfield(n,"penalty",p) +function pool.penalty(p) + local n = copy_node(penalty) + n.penalty = p return n end -function nutpool.kern(k) - local n = copy_nut(kern) - setfield(n,"kern",k) +function pool.kern(k) + local n = copy_node(kern) + n.kern = k return n end -function nutpool.fontkern(k) - local n = copy_nut(fontkern) - setfield(n,"kern",k) +function pool.fontkern(k) + local n = copy_node(fontkern) + n.kern = k return n end -function nutpool.gluespec(width,stretch,shrink,stretch_order,shrink_order) - local s = copy_nut(glue_spec) - if width then setfield(s,"width",width) end - if stretch then setfield(s,"stretch",stretch) end - if shrink then setfield(s,"shrink",shrink) end - if stretch_order then setfield(s,"stretch_order",stretch_order) end - if shrink_order then setfield(s,"shrink_order",shrink_order) end +function pool.gluespec(width,stretch,shrink,stretch_order,shrink_order) + local s = copy_node(glue_spec) + if width then s.width = width end + if stretch then s.stretch = stretch end + if shrink then s.shrink = shrink end + if stretch_order then s.stretch_order = stretch_order end + if shrink_order then s.shrink_order = shrink_order end return s end local function someskip(skip,width,stretch,shrink,stretch_order,shrink_order) - local n = copy_nut(skip) + local n = copy_node(skip) if not width then -- no spec elseif width == false or tonumber(width) then - local s = copy_nut(glue_spec) - if width then setfield(s,"width",width) end - if stretch then setfield(s,"stretch",stretch) end - if shrink then setfield(s,"shrink",shrink) end - if stretch_order then setfield(s,"stretch_order",stretch_order) end - if shrink_order then setfield(s,"shrink_order",shrink_order) end - setfield(n,"spec",s) + local s = copy_node(glue_spec) + if width then s.width = width end + if stretch then s.stretch = stretch end + if shrink then s.shrink = shrink end + if stretch_order then s.stretch_order = stretch_order end + if shrink_order then s.shrink_order = shrink_order end + n.spec = s else -- shared - setfield(n,"spec",copy_nut(width)) + n.spec = copy_node(width) end return n end -function nutpool.stretch(a,b) - local n = copy_nut(glue) - local s = copy_nut(glue_spec) +function pool.stretch(a,b) + local n = copy_node(glue) + local s = copy_node(glue_spec) if b then - setfield(s,"stretch",a) - setfield(s,"stretch_order",b) + s.stretch = a + s.stretch_order = b else - setfield(s,"stretch",1) - setfield(s,"stretch_order",a or 1) + s.stretch = 1 + s.stretch_order = a or 1 end - setfield(n,"spec",s) + n.spec = s return n end -function nutpool.shrink(a,b) - local n = copy_nut(glue) - local s = copy_nut(glue_spec) +function pool.shrink(a,b) + local n = copy_node(glue) + local s = copy_node(glue_spec) if b then - setfield(s,"shrink",a) - setfield(s,"shrink_order",b) + s.shrink = a + s.shrink_order = b else - setfield(s,"shrink",1) - setfield(s,"shrink_order",a or 1) + s.shrink = 1 + s.shrink_order = a or 1 end - setfield(n,"spec",s) + n.spec = s return n end -function nutpool.glue(width,stretch,shrink,stretch_order,shrink_order) + +function pool.glue(width,stretch,shrink,stretch_order,shrink_order) return someskip(glue,width,stretch,shrink,stretch_order,shrink_order) end -function nutpool.leftskip(width,stretch,shrink,stretch_order,shrink_order) +function pool.leftskip(width,stretch,shrink,stretch_order,shrink_order) return someskip(leftskip,width,stretch,shrink,stretch_order,shrink_order) end -function nutpool.rightskip(width,stretch,shrink,stretch_order,shrink_order) +function pool.rightskip(width,stretch,shrink,stretch_order,shrink_order) return someskip(rightskip,width,stretch,shrink,stretch_order,shrink_order) end -function nutpool.lineskip(width,stretch,shrink,stretch_order,shrink_order) +function pool.lineskip(width,stretch,shrink,stretch_order,shrink_order) return someskip(lineskip,width,stretch,shrink,stretch_order,shrink_order) end -function nutpool.baselineskip(width,stretch,shrink) +function pool.baselineskip(width,stretch,shrink) return someskip(baselineskip,width,stretch,shrink) end -function nutpool.disc() - return copy_nut(disc) +function pool.disc() + return copy_node(disc) end -function nutpool.textdir(dir) - local t = copy_nut(textdir) - setfield(t,"dir",dir) +function pool.textdir(dir) + local t = copy_node(textdir) + t.dir = dir return t end -function nutpool.rule(width,height,depth,dir) -- w/h/d == nil will let them adapt - local n = copy_nut(rule) - if width then setfield(n,"width",width) end - if height then setfield(n,"height",height) end - if depth then setfield(n,"depth",depth) end - if dir then setfield(n,"dir",dir) end +function pool.rule(width,height,depth,dir) -- w/h/d == nil will let them adapt + local n = copy_node(rule) + if width then n.width = width end + if height then n.height = height end + if depth then n.depth = depth end + if dir then n.dir = dir end return n end --- if node.has_field(latelua,'string') then - function nutpool.latelua(code) - local n = copy_nut(latelua) - setfield(n,"string",code) +if node.has_field(latelua,'string') then + function pool.latelua(code) + local n = copy_node(latelua) + n.string = code + return n + end +else + function pool.latelua(code) + local n = copy_node(latelua) + n.data = code return n end --- else --- function nutpool.latelua(code) --- local n = copy_nut(latelua) --- setfield(n,"data",code) --- return n --- end --- end - -function nutpool.leftmarginkern(glyph,width) - local n = copy_nut(left_margin_kern) +end + +function pool.leftmarginkern(glyph,width) + local n = copy_node(left_margin_kern) if not glyph then report_nodes("invalid pointer to left margin glyph node") - elseif getid(glyph) ~= glyph_code then + elseif glyph.id ~= glyph_code then report_nodes("invalid node type %a for %s margin glyph node",nodecodes[glyph],"left") else - setfield(n,"glyph",glyph) + n.glyph = glyph end if width then - setfield(n,"width",width) + n.width = width end return n end -function nutpool.rightmarginkern(glyph,width) - local n = copy_nut(right_margin_kern) +function pool.rightmarginkern(glyph,width) + local n = copy_node(right_margin_kern) if not glyph then report_nodes("invalid pointer to right margin glyph node") - elseif getid(glyph) ~= glyph_code then + elseif glyph.id ~= glyph_code then report_nodes("invalid node type %a for %s margin glyph node",nodecodes[p],"right") else - setfield(n,"glyph",glyph) + n.glyph = glyph end if width then - setfield(n,"width",width) + n.width = width end return n end -function nutpool.temp() - return copy_nut(temp) +function pool.temp() + return copy_node(temp) end -function nutpool.noad() - return copy_nut(noad) +function pool.noad() + return copy_node(noad) end -function nutpool.hlist(list,width,height,depth) - local n = copy_nut(hlist) +function pool.hlist(list,width,height,depth) + local n = copy_node(hlist) if list then - setfield(n,"list",list) + n.list = list end if width then - setfield(n,"width",width) + n.width = width end if height then - setfield(n,"height",height) + n.height = height end if depth then - setfield(n,"depth",depth) + n.depth = depth end return n end -function nutpool.vlist(list,width,height,depth) - local n = copy_nut(vlist) +function pool.vlist(list,width,height,depth) + local n = copy_node(vlist) if list then - setfield(n,"list",list) + n.list = list end if width then - setfield(n,"width",width) + n.width = width end if height then - setfield(n,"height",height) + n.height = height end if depth then - setfield(n,"depth",depth) + n.depth = depth end return n end +--[[ +<p>At some point we ran into a problem that the glue specification +of the zeropoint dimension was overwritten when adapting a glue spec +node. This is a side effect of glue specs being shared. After a +couple of hours tracing and debugging Taco and I came to the +conclusion that it made no sense to complicate the spec allocator +and settled on a writable flag. This all is a side effect of the +fact that some glues use reserved memory slots (with the zeropoint +glue being a noticeable one). So, next we wrap this into a function +and hide it for the user. And yes, LuaTeX now gives a warning as +well.</p> +]]-- + +function nodes.writable_spec(n) -- not pool + local spec = n.spec + if not spec then + spec = copy_node(glue_spec) + n.spec = spec + elseif not spec.writable then + spec = copy_node(spec) + n.spec = spec + end + return spec +end + -- local num = userids["my id"] -- local str = userids[num] -function nutpool.usernumber(id,num) - local n = copy_nut(user_n) +local userids = allocate() pool.userids = userids +local lastid = 0 + +setmetatable(userids, { + __index = function(t,k) + if type(k) == "string" then + lastid = lastid + 1 + rawset(userids,lastid,k) + rawset(userids,k,lastid) + return lastid + else + rawset(userids,k,k) + return k + end + end, + __call = function(t,k) + return t[k] + end +} ) + +function pool.usernumber(id,num) + local n = copy_node(user_n) if num then - setfield(n,"user_id",id) - setfield(n,"value",num) + n.user_id, n.value = id, num elseif id then - setfield(n,"value",id) + n.value = id end return n end -function nutpool.userlist(id,list) - local n = copy_nut(user_l) +function pool.userlist(id,list) + local n = copy_node(user_l) if list then - setfield(n,"user_id",id) - setfield(n,"value",list) + n.user_id, n.value = id, list else - setfield(n,"value",id) + n.value = id end return n end -function nutpool.userstring(id,str) - local n = copy_nut(user_s) +function pool.userstring(id,str) + local n = copy_node(user_s) if str then - setfield(n,"user_id",id) - setfield(n,"value",str) + n.user_id, n.value = id, str else - setfield(n,"value",id) + n.value = id end return n end -function nutpool.usertokens(id,tokens) - local n = copy_nut(user_t) +function pool.usertokens(id,tokens) + local n = copy_node(user_t) if tokens then - setfield(n,"user_id",id) - setfield(n,"value",tokens) + n.user_id, n.value = id, tokens else - setfield(n,"value",id) + n.value = id end return n end -function nutpool.special(str) - local n = copy_nut(special) - setfield(n,"data",str) +function pool.special(str) + local n = copy_node(special) + n.data = str return n end --- housekeeping - -local function cleanup(nofboxes) -- todo - if nodes.tracers.steppers then -- to be resolved - nodes.tracers.steppers.reset() -- todo: make a registration subsystem - end - local nl, nr = 0, nofreserved - for i=1,nofreserved do - local ri = reserved[i] - -- if not (getid(ri) == glue_spec and not getfield(ri,"is_writable")) then - free_nut(reserved[i]) - -- end - end - if nofboxes then - for i=0,nofboxes do - local l = getbox(i) - if l then - free_nut(l) -- also list ? - nl = nl + 1 - end - end - end - reserved = { } - nofreserved = 0 - return nr, nl, nofboxes -- can be nil -end - - -local function usage() - local t = { } - for n, tag in gmatch(status.node_mem_usage,"(%d+) ([a-z_]+)") do - t[tag] = n - end - return t -end - -nutpool .cleanup = cleanup -nodepool.cleanup = cleanup - -nutpool .usage = usage -nodepool.usage = usage - --- end - statistics.register("cleaned up reserved nodes", function() - return format("%s nodes, %s lists of %s", cleanup(texgetcount("c_syst_last_allocated_box"))) + return format("%s nodes, %s lists of %s", pool.cleanup(texgetcount("c_syst_last_allocated_box"))) end) -- \topofboxstack statistics.register("node memory usage", function() -- comes after cleanup ! return status.node_mem_usage end) -lua.registerfinalizer(cleanup, "cleanup reserved nodes") +lua.registerfinalizer(pool.cleanup, "cleanup reserved nodes") diff --git a/tex/context/base/node-rul.lua b/tex/context/base/node-rul.lua index 6f3bc9df9..96d6bdf41 100644 --- a/tex/context/base/node-rul.lua +++ b/tex/context/base/node-rul.lua @@ -13,28 +13,12 @@ if not modules then modules = { } end modules ['node-rul'] = { local attributes, nodes, node = attributes, nodes, node -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getlist = nuts.getlist - -local nodecodes = nodes.nodecodes -local tasks = nodes.tasks - -local glyph_code = nodecodes.glyph -local disc_code = nodecodes.disc -local rule_code = nodecodes.rule +local nodecodes = nodes.nodecodes +local tasks = nodes.tasks + +local glyph_code = nodecodes.glyph +local disc_code = nodecodes.disc +local rule_code = nodecodes.rule function nodes.striprange(first,last) -- todo: dir if first and last then -- just to be sure @@ -42,11 +26,11 @@ function nodes.striprange(first,last) -- todo: dir return first, last end while first and first ~= last do - local id = getid(first) + local id = first.id if id == glyph_code or id == disc_code then -- or id == rule_code break else - first = getnext(first) + first = first.next end end if not first then @@ -55,13 +39,13 @@ function nodes.striprange(first,last) -- todo: dir return first, last end while last and last ~= first do - local id = getid(last) + local id = last.id if id == glyph_code or id == disc_code then -- or id == rule_code break else - local prev = getprev(last) -- luatex < 0.70 has italic correction kern not prev'd + local prev = last.prev -- luatex < 0.70 has italic correction kern not prev'd if prev then - last = prev + last = last.prev else break end @@ -89,12 +73,12 @@ local a_color = attributes.private('color') local a_transparency = attributes.private('transparency') local a_colorspace = attributes.private('colormodel') -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local list_dimensions = nuts.dimensions -local hpack_nodes = nuts.hpack - +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after local striprange = nodes.striprange +local list_dimensions = node.dimensions + +local hpack_nodes = node.hpack local fontdata = fonts.hashes.identifiers local variables = interfaces.variables @@ -127,7 +111,7 @@ local dir_code = whatcodes.dir local kerning_code = kerncodes.kern -local nodepool = nuts.pool +local nodepool = nodes.pool local new_rule = nodepool.rule local new_kern = nodepool.kern @@ -157,9 +141,9 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi local f, l, a, d, i, class local continue, done, strip, level = false, false, true, -1 while n do - local id = getid(n) + local id = n.id if id == glyph_code or id == rule_code then - local aa = getattr(n,attribute) + local aa = n[attribute] if aa then if aa == a then if not f then -- ? @@ -188,13 +172,13 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi end f, l, a = nil, nil, nil end --- elseif f and (id == disc_code or (id == kern_code and getsubtype(n) == kerning_code)) then +-- elseif f and (id == disc_code or (id == kern_code and n.subtype == kerning_code)) then -- l = n elseif id == disc_code then if f then l = n end - elseif id == kern_code and getsubtype(n) == kerning_code then + elseif id == kern_code and n.subtype == kerning_code then if f then l = n end @@ -203,11 +187,11 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi head, done = flush(head,f,l,d,level,parent,strip), true f, l, a = nil, nil, nil end - local list = getlist(n) + local list = n.list if list then - setfield(n,"list",(processwords(attribute,data,flush,list,n))) -- watch () + n.list = processwords(attribute,data,flush,list,n) end - elseif checkdir and id == whatsit_code and getsubtype(n) == dir_code then -- only changes in dir, we assume proper boundaries + elseif checkdir and id == whatsit_code and n.subtype == dir_code then -- only changes in dir, we assume proper boundaries if f and a then l = n end @@ -219,8 +203,8 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi -- l = n elseif id == glue_code then -- catch \underbar{a} \underbar{a} (subtype test is needed) - local subtype = getsubtype(n) - if getattr(n,attribute) and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code) then + local subtype = n.subtype + if n[attribute] and (subtype == userskip_code or subtype == spaceskip_code or subtype == xspaceskip_code) then l = n else head, done = flush(head,f,l,d,level,parent,strip), true @@ -232,7 +216,7 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi f, l, a = nil, nil, nil end end - n = getnext(n) + n = n.next end if f then head, done = flush(head,f,l,d,level,parent,strip), true @@ -243,16 +227,7 @@ local function processwords(attribute,data,flush,head,parent) -- we have hlistdi end end --- nodes.processwords = processwords - -nodes.processwords = function(attribute,data,flush,head,parent) -- we have hlistdir and local dir - head = tonut(head) - if parent then - parent = tonut(parent) - end - local head, done = processwords(attribute,data,flush,head,parent) - return tonode(head), done -end +nodes.processwords = processwords -- @@ -271,7 +246,7 @@ end local a_viewerlayer = attributes.private("viewerlayer") local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but acceptable for this purpose - if getid(f) ~= glyph_code then + if f.id ~= glyph_code then -- saveguard ... we need to deal with rules and so (math) return head end @@ -289,16 +264,16 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a if not f then return head end - local w = list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),f,getnext(l)) + local w = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,f,l.next) local method, offset, continue, dy, order, max = d.method, d.offset, d.continue, d.dy, d.order, d.max local rulethickness, unit = d.rulethickness, d.unit local ma, ca, ta = d.ma, d.ca, d.ta - local colorspace = ma > 0 and ma or getattr(f,a_colorspace) or 1 - local color = ca > 0 and ca or getattr(f,a_color) - local transparency = ta > 0 and ta or getattr(f,a_transparency) + local colorspace = ma > 0 and ma or f[a_colorspace] or 1 + local color = ca > 0 and ca or f[a_color] + local transparency = ta > 0 and ta or f[a_transparency] local foreground = order == v_foreground - local e = dimenfactor(unit,getfont(f)) -- what if no glyph node + local e = dimenfactor(unit,f.font) -- what if no glyph node local rt = tonumber(rulethickness) if rt then @@ -306,7 +281,7 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a else local n, u = splitdimen(rulethickness) if n and u then -- we need to intercept ex and em and % and ... - rulethickness = n * dimenfactor(u,fontdata[getfont(f)]) / 2 + rulethickness = n * dimenfactor(u,fontdata[f.font]) / 2 else rulethickness = 1/5 end @@ -325,18 +300,18 @@ local function flush_ruled(head,f,l,d,level,parent,strip) -- not that fast but a local ht = (offset+(i-1)*dy)*e + rulethickness - m local dp = -(offset+(i-1)*dy)*e + rulethickness + m local r = new_rule(w,ht,dp) - local v = getattr(f,a_viewerlayer) + local v = f[a_viewerlayer] -- quick hack if v then - setattr(r,a_viewerlayer,v) + r[a_viewerlayer] = v end -- if color then - setattr(r,a_colorspace,colorspace) - setattr(r,a_color,color) + r[a_colorspace] = colorspace + r[a_color] = color end if transparency then - setattr(r,a_transparency,transparency) + r[a_transparency] = transparency end local k = new_kern(-w) if foreground then @@ -390,27 +365,21 @@ local function flush_shifted(head,first,last,data,level,parent,strip) -- not tha if true then first, last = striprange(first,last) end - local prev = getprev(first) - local next = getnext(last) - setfield(first,"prev",nil) - setfield(last,"next",nil) - local width, height, depth = list_dimensions(getfield(parent,"glue_set"),getfield(parent,"glue_sign"),getfield(parent,"glue_order"),first,next) + local prev, next = first.prev, last.next + first.prev, last.next = nil, nil + local width, height, depth = list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,first,next) local list = hpack_nodes(first,width,"exactly") if first == head then head = list end if prev then - setfield(prev,"next",list) - setfield(list,"prev",prev) + prev.next, list.prev = list, prev end if next then - setfield(next,"prev",list) - setfield(list,"next",next) + next.prev, list.next = list, next end - local raise = data.dy * dimenfactor(data.unit,fontdata[getfont(first)]) - setfield(list,"shift",raise) - setfield(list,"height",height) - setfield(list,"depth",depth) + local raise = data.dy * dimenfactor(data.unit,fontdata[first.font]) + list.shift, list.height, list.depth = raise, height, depth if trace_shifted then report_shifted("width %p, nodes %a, text %a",width,n_tostring(first,last),n_tosequence(first,last,true)) end diff --git a/tex/context/base/node-tra.lua b/tex/context/base/node-tra.lua index 081107277..9617f7476 100644 --- a/tex/context/base/node-tra.lua +++ b/tex/context/base/node-tra.lua @@ -34,30 +34,9 @@ nodes.handlers = handlers local injections = nodes.injections or { } nodes.injections = injections -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getchar = nuts.getchar -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist - -local setattr = nuts.setattr - -local flush_list = nuts.flush_list -local count_nodes = nuts.count -local used_nodes = nuts.usedlist - -local traverse_by_id = nuts.traverse_id -local traverse_nodes = nuts.traverse -local d_tostring = nuts.tostring - -local nutpool = nuts.pool -local new_rule = nutpool.rule +local traverse_nodes = node.traverse +local traverse_by_id = node.traverse_id +local count_nodes = nodes.count local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -77,6 +56,9 @@ local gluespec_code = nodecodes.gluespec local localpar_code = whatcodes.localpar local dir_code = whatcodes.dir +local nodepool = nodes.pool +local new_rule = nodepool.rule + local dimenfactors = number.dimenfactors local formatters = string.formatters @@ -86,16 +68,15 @@ function nodes.showlist(head, message) if message then report_nodes(message) end - for n in traverse_nodes(tonut(head)) do - report_nodes(d_tostring(n)) + for n in traverse_nodes(head) do + report_nodes(tostring(n)) end end function nodes.handlers.checkglyphs(head,message) - local h = tonut(head) local t = { } - for g in traverse_by_id(glyph_code,h) do - t[#t+1] = formatters["%U:%s"](getchar(g),getsubtype(g)) + for g in traverse_by_id(glyph_code,head) do + t[#t+1] = formatters["%U:%s"](g.char,g.subtype) end if #t > 0 then if message and message ~= "" then @@ -109,12 +90,12 @@ end function nodes.handlers.checkforleaks(sparse) local l = { } - local q = used_nodes() - for p in traverse_nodes(q) do - local s = table.serialize(nodes.astable(p,sparse),nodecodes[getid(p)]) + local q = node.usedlist() + for p in traverse(q) do + local s = table.serialize(nodes.astable(p,sparse),nodecodes[p.id]) l[s] = (l[s] or 0) + 1 end - flush_list(q) + node.flush_list(q) for k, v in next, l do report_nodes("%s * %s",v,k) end @@ -124,40 +105,39 @@ local f_sequence = formatters["U+%04X:%s"] local function tosequence(start,stop,compact) if start then - start = tonut(start) - stop = stop and tonut(stop) local t = { } while start do - local id = getid(start) + local id = start.id if id == glyph_code then - local c = getchar(start) + local c = start.char if compact then - local components = getfield(start,"components") - if components then - t[#t+1] = tosequence(components,nil,compact) + if start.components then + t[#t+1] = tosequence(start.components,nil,compact) else t[#t+1] = utfchar(c) end else t[#t+1] = f_sequence(c,utfchar(c)) end + elseif id == whatsit_code and start.subtype == localpar_code or start.subtype == dir_code then + t[#t+1] = "[" .. start.dir .. "]" elseif id == rule_code then if compact then t[#t+1] = "|" else t[#t+1] = nodecodes[id] end - elseif id == whatsit_code and getsubtype(start) == localpar_code or getsubtype(start) == dir_code then - t[#t+1] = "[" .. getfield(start,"dir") .. "]" - elseif compact then - t[#t+1] = "[]" else - t[#t+1] = nodecodes[id] + if compact then + t[#t+1] = "[]" + else + t[#t+1] = nodecodes[id] + end end if start == stop then break else - start = getnext(start) + start = start.next end end if compact then @@ -173,23 +153,21 @@ end nodes.tosequence = tosequence function nodes.report(t,done) - report_nodes("output %a, %changed %a, %s nodes",status.output_active,done,count_nodes(tonut(t))) + report_nodes("output %a, %changed %a, %s nodes",status.output_active,done,count_nodes(t)) end function nodes.packlist(head) local t = { } - for n in traverse_nodes(tonut(head)) do - t[#t+1] = d_tostring(n) + for n in traverse(head) do + t[#t+1] = tostring(n) end return t end function nodes.idstostring(head,tail) - head = tonut(head) - tail = tail and tonut(tail) local t, last_id, last_n = { }, nil, 0 for n in traverse_nodes(head,tail) do -- hm, does not stop at tail - local id = getid(n) + local id = n.id if not last_id then last_id, last_n = id, 1 elseif last_id == id then @@ -217,8 +195,6 @@ function nodes.idstostring(head,tail) end -- function nodes.xidstostring(head,tail) -- only for special tracing of backlinks --- head = tonut(head) --- tail = tonut(tail) -- local n = head -- while n.next do -- n = n.next @@ -241,7 +217,7 @@ end -- if n == head then -- break -- end --- n = getprev(n) +-- n = n.prev -- end -- if not last_id then -- t[#t+1] = "no nodes" @@ -254,56 +230,51 @@ end -- end local function showsimplelist(h,depth,n) - h = h and tonut(h) while h do report_nodes("% w%s",n,d_tostring(h)) if not depth or n < depth then - local id = getid(h) + local id = h.id if id == hlist_code or id == vlist_code then - showsimplelist(getlist(h),depth,n+1) + showsimplelist(h.list,depth,n+1) end end - h = getnext(h) + h = h.next end end --- \startluacode --- callback.register('buildpage_filter',function() nodes.show_simple_list(tex.lists.contrib_head) end) --- \stopluacode --- \vbox{b\footnote{n}a} --- \startluacode --- callback.register('buildpage_filter',nil) --- \stopluacode +--~ \startluacode +--~ callback.register('buildpage_filter',function() nodes.show_simple_list(tex.lists.contrib_head) end) +--~ \stopluacode +--~ \vbox{b\footnote{n}a} +--~ \startluacode +--~ callback.register('buildpage_filter',nil) +--~ \stopluacode nodes.showsimplelist = function(h,depth) showsimplelist(h,depth,0) end local function listtoutf(h,joiner,textonly,last) + local joiner = (joiner == true and utfchar(0x200C)) or joiner -- zwnj local w = { } while h do - local id = getid(h) + local id = h.id if id == glyph_code then -- always true - local c = getchar(h) + local c = h.char w[#w+1] = c >= 0 and utfchar(c) or formatters["<%i>"](c) if joiner then w[#w+1] = joiner end elseif id == disc_code then - local pre = getfield(h,"pre") - local pos = getfield(h,"post") - local rep = getfield(h,"replace") + local pre = h.pre + local pos = h.post + local rep = h.replace w[#w+1] = formatters["[%s|%s|%s]"] ( pre and listtoutf(pre,joiner,textonly) or "", pos and listtoutf(pos,joiner,textonly) or "", rep and listtoutf(rep,joiner,textonly) or "" ) elseif textonly then - if id == glue_code then - local spec = getfield(h,"spec") - if spec and getfield(spec,"width") > 0 then - w[#w+1] = " " - end - elseif id == hlist_code or id == vlist_code then - w[#w+1] = "[]" + if id == glue_code and h.spec and h.spec.width > 0 then + w[#w+1] = " " end else w[#w+1] = "[-]" @@ -311,28 +282,24 @@ local function listtoutf(h,joiner,textonly,last) if h == last then break else - h = getnext(h) + h = h.next end end return concat(w) end -function nodes.listtoutf(h,joiner,textonly,last) - local joiner = joiner == true and utfchar(0x200C) or joiner -- zwnj - return listtoutf(tonut(h),joiner,textonly,last and tonut(last)) -end +nodes.listtoutf = listtoutf local what = { [0] = "unknown", "line", "box", "indent", "row", "cell" } local function showboxes(n,symbol,depth) - depth = depth or 0 - symbol = symbol or "." - for n in traverse_nodes(tonut(n)) do - local id = getid(n) + depth, symbol = depth or 0, symbol or "." + for n in traverse_nodes(n) do + local id = n.id if id == hlist_code or id == vlist_code then - local s = getsubtype(n) + local s = n.subtype report_nodes(rep(symbol,depth) .. what[s] or s) - showboxes(getlist(n),symbol,depth+1) + showboxes(n.list,symbol,depth+1) end end end @@ -355,8 +322,15 @@ local stripper = lpeg.patterns.stripzeros local dimenfactors = number.dimenfactors -local function nodetodimen(d,unit,fmt,strip) - d = tonut(d) -- tricky: direct nuts are an issue +local function numbertodimen(d,unit,fmt,strip) + if not d then + local str = formatters[fmt](0,unit) + return strip and lpegmatch(stripper,str) or str + end + local t = type(d) + if t == 'string' then + return d + end if unit == true then unit = "pt" fmt = "%0.5f%s" @@ -368,23 +342,27 @@ local function nodetodimen(d,unit,fmt,strip) fmt = "%0.5f%s" end end - local id = getid(d) + if t == "number" then + local str = formatters[fmt](d*dimenfactors[unit],unit) + return strip and lpegmatch(stripper,str) or str + end + local id = d.id if id == kern_code then - local str = formatters[fmt](getfield(d,"width")*dimenfactors[unit],unit) + local str = formatters[fmt](d.width*dimenfactors[unit],unit) return strip and lpegmatch(stripper,str) or str end if id == glue_code then - d = getfield(d,"spec") + d = d.spec end - if not d or not getid(d) == gluespec_code then + if not d or not d.id == gluespec_code then local str = formatters[fmt](0,unit) return strip and lpegmatch(stripper,str) or str end - local width = getfield(d,"width") - local plus = getfield(d,"stretch_order") - local minus = getfield(d,"shrink_order") - local stretch = getfield(d,"stretch") - local shrink = getfield(d,"shrink") + local width = d.width + local plus = d.stretch_order + local minus = d.shrink_order + local stretch = d.stretch + local shrink = d.shrink if plus ~= 0 then plus = " plus " .. stretch/65536 .. fillcodes[plus] elseif stretch ~= 0 then @@ -401,39 +379,11 @@ local function nodetodimen(d,unit,fmt,strip) else minus = "" end - local str = formatters[fmt](getfield(d,"width")*dimenfactors[unit],unit) + local str = formatters[fmt](d.width*dimenfactors[unit],unit) return (strip and lpegmatch(stripper,str) or str) .. plus .. minus end -local function numbertodimen(d,unit,fmt,strip) - if not d then - local str = formatters[fmt](0,unit) - return strip and lpegmatch(stripper,str) or str - end - local t = type(d) - if t == 'string' then - return d - elseif t == "number" then - if unit == true then - unit = "pt" - fmt = "%0.5f%s" - else - unit = unit or 'pt' - if not fmt then - fmt = "%s%s" - elseif fmt == true then - fmt = "%0.5f%s" - end - end - local str = formatters[fmt](d*dimenfactors[unit],unit) - return strip and lpegmatch(stripper,str) or str - else - return nodetodimen(d,unit,fmt,strip) -- real node - end -end - number.todimen = numbertodimen -nodes .todimen = nodetodimen function number.topoints (n,fmt) return numbertodimen(n,"pt",fmt) end function number.toinches (n,fmt) return numbertodimen(n,"in",fmt) end @@ -448,19 +398,6 @@ function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end -function nodes.topoints (n,fmt) return nodetodimen(n,"pt",fmt) end -function nodes.toinches (n,fmt) return nodetodimen(n,"in",fmt) end -function nodes.tocentimeters (n,fmt) return nodetodimen(n,"cm",fmt) end -function nodes.tomillimeters (n,fmt) return nodetodimen(n,"mm",fmt) end -function nodes.toscaledpoints(n,fmt) return nodetodimen(n,"sp",fmt) end -function nodes.toscaledpoints(n) return n .. "sp" end -function nodes.tobasepoints (n,fmt) return nodetodimen(n,"bp",fmt) end -function nodes.topicas (n,fmt) return nodetodimen(n "pc",fmt) end -function nodes.todidots (n,fmt) return nodetodimen(n,"dd",fmt) end -function nodes.tociceros (n,fmt) return nodetodimen(n,"cc",fmt) end -function nodes.tonewdidots (n,fmt) return nodetodimen(n,"nd",fmt) end -function nodes.tonewciceros (n,fmt) return nodetodimen(n,"nc",fmt) end - -- stop redefinition local points = function(n) @@ -506,13 +443,8 @@ number.basepoints = basepoints number.pts = pts number.nopts = nopts -nodes.points = function(n) return numbertodimen(n,"pt",true,true) end -nodes.basepoints = function(n) return numbertodimen(n,"bp",true,true) end -nodes.pts = function(n) return numbertodimen(n,"pt",true) end -nodes.nopts = function(n) return format("%.5f",n*ptfactor) end - -local colors = { } -tracers.colors = colors +local colors = { } +tracers.colors = colors local unsetvalue = attributes.unsetvalue @@ -522,34 +454,36 @@ local m_color = attributes.list[a_color] or { } function colors.set(n,c,s) local mc = m_color[c] - local nn = tonut(n) - if mc then - local mm = s or texgetattribute(a_colormodel) - setattr(nn,a_colormodel,mm <= 0 and mm or 1) - setattr(nn,a_color,mc) + if not mc then + n[a_color] = unsetvalue else - setattr(nn,a_color,unsetvalue) + if not n[a_colormodel] then + n[a_colormodel] = s or 1 + end + n[a_color] = mc end return n end function colors.setlist(n,c,s) - local nn = tonut(n) - local mc = m_color[c] or unsetvalue - local mm = s or texgetattribute(a_colormodel) - if mm <= 0 then - mm = 1 - end - while nn do - setattr(nn,a_colormodel,mm) - setattr(nn,a_color,mc) - nn = getnext(nn) + local f = n + while n do + local mc = m_color[c] + if not mc then + n[a_color] = unsetvalue + else + if not n[a_colormodel] then + n[a_colormodel] = s or 1 + end + n[a_color] = mc + end + n = n.next end - return n + return f end function colors.reset(n) - setattr(tonut(n),a_color,unsetvalue) + n[a_color] = unsetvalue return n end @@ -562,22 +496,31 @@ local a_transparency = attributes.private('transparency') local m_transparency = attributes.list[a_transparency] or { } function transparencies.set(n,t) - setattr(tonut(n),a_transparency,m_transparency[t] or unsetvalue) + local mt = m_transparency[t] + if not mt then + n[a_transparency] = unsetvalue + else + n[a_transparency] = mt + end return n end function transparencies.setlist(n,c,s) - local nn = tonut(n) - local mt = m_transparency[c] or unsetvalue - while nn do - setattr(nn,a_transparency,mt) - nn = getnext(nn) + local f = n + while n do + local mt = m_transparency[c] + if not mt then + n[a_transparency] = unsetvalue + else + n[a_transparency] = mt + end + n = n.next end - return n + return f end function transparencies.reset(n) - setattr(n,a_transparency,unsetvalue) + n[a_transparency] = unsetvalue return n end @@ -594,76 +537,52 @@ end -- although tracers are used seldom local function setproperties(n,c,s) - local nn = tonut(n) local mm = texgetattribute(a_colormodel) - setattr(nn,a_colormodel,mm > 0 and mm or 1) - setattr(nn,a_color,m_color[c]) - setattr(nn,a_transparency,m_transparency[c]) + n[a_colormodel] = mm > 0 and mm or 1 + n[a_color] = m_color[c] + n[a_transparency] = m_transparency[c] return n end tracers.setproperties = setproperties -function tracers.setlist(n,c,s) - local nn = tonut(n) +function tracers.setlistv(n,c,s) + local f = n local mc = m_color[c] local mt = m_transparency[c] local mm = texgetattribute(a_colormodel) if mm <= 0 then mm = 1 end - while nn do - setattr(nn,a_colormodel,mm) - setattr(nn,a_color,mc) - setattr(nn,a_transparency,mt) - nn = getnext(nn) + while n do + n[a_colormodel] = mm + n[a_color] = mc + n[a_transparency] = mt + n = n.next end - return n + return f end function tracers.resetproperties(n) - local nn = tonut(n) - setattr(nn,a_color,unsetvalue) - setattr(nn,a_transparency,unsetvalue) + n[a_color] = unsetvalue + n[a_transparency] = unsetvalue return n end --- this one returns a nut +function tracers.rule(w,h,d,c,s) -- so some day we can consider using literals (speedup) + return setproperties(new_rule(w,h,d),c,s) +end + +-- only nodes local nodestracerpool = { } -local nutstracerpool = { } tracers.pool = { nodes = nodestracerpool, - nuts = nutstracerpool, } -table.setmetatableindex(nodestracerpool,function(t,k,v) - local f = nutstracerpool[k] - local v = function(...) - return tonode(f(...)) - end - t[k] = v - return v -end) - -function nutstracerpool.rule(w,h,d,c,s) -- so some day we can consider using literals (speedup) +function nodestracerpool.rule(w,h,d,c,s) -- so some day we can consider using literals (speedup) return setproperties(new_rule(w,h,d),c,s) end tracers.rule = nodestracerpool.rule -- for a while - --- local function show(head,n,message) --- print("START",message or "") --- local i = 0 --- for current in traverse(head) do --- local prev = getprev(current) --- local next = getnext(current) --- i = i + 1 --- print(i, prev and nodecodes[getid(prev)],nodecodes[getid(current)],next and nodecodes[getid(next)]) --- if i == n then --- break --- end --- end --- print("STOP", message or "") --- end diff --git a/tex/context/base/node-tst.lua b/tex/context/base/node-tst.lua index 7f5102d5f..bfe0051bd 100644 --- a/tex/context/base/node-tst.lua +++ b/tex/context/base/node-tst.lua @@ -24,26 +24,17 @@ local rightskip_code = skipcodes.rightskip local abovedisplayshortskip_code = skipcodes.abovedisplayshortskip local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip -local nuts = nodes.nuts +local find_node_tail = node.tail or node.slide -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getchar = nuts.getchar -local getsubtype = nuts.getsubtype - -local find_node_tail = nuts.tail - -function nuts.leftmarginwidth(n) -- todo: three values +function nodes.leftmarginwidth(n) -- todo: three values while n do - local id = getid(n) + local id = n.id if id == glue_code then - return getsubtype(n) == leftskip_code and getfield(getfield(n,"spec"),"width") or 0 + return n.subtype == leftskip_code and n.spec.width or 0 elseif id == whatsit_code then - n = getnext(n) + n = n.next elseif id == hlist_code then - return getfield(n,"width") + return n.width else break end @@ -51,15 +42,15 @@ function nuts.leftmarginwidth(n) -- todo: three values return 0 end -function nuts.rightmarginwidth(n) +function nodes.rightmarginwidth(n) if n then n = find_node_tail(n) while n do - local id = getid(n) + local id = n.id if id == glue_code then - return getsubtype(n) == rightskip_code and getfield(getfield(n,"spec"),"width") or 0 + return n.subtype == rightskip_code and n.spec.width or 0 elseif id == whatsit_code then - n = getprev(n) + n = n.prev else break end @@ -68,15 +59,15 @@ function nuts.rightmarginwidth(n) return false end -function nuts.somespace(n,all) +function nodes.somespace(n,all) if n then - local id = getid(n) + local id = n.id if id == glue_code then - return (all or (getfield(getfield(n,"spec"),"width") ~= 0)) and glue_code + return (all or (n.spec.width ~= 0)) and glue_code elseif id == kern_code then - return (all or (getfield(n,"kern") ~= 0)) and kern + return (all or (n.kern ~= 0)) and kern elseif id == glyph_code then - local category = chardata[getchar(n)].category + local category = chardata[n.char].category -- maybe more category checks are needed return (category == "zs") and glyph_code end @@ -84,12 +75,12 @@ function nuts.somespace(n,all) return false end -function nuts.somepenalty(n,value) +function nodes.somepenalty(n,value) if n then - local id = getid(n) + local id = n.id if id == penalty_code then if value then - return getfield(n,"penalty") == value + return n.penalty == value else return true end @@ -98,38 +89,32 @@ function nuts.somepenalty(n,value) return false end -function nuts.is_display_math(head) - local n = getprev(head) +function nodes.is_display_math(head) + local n = head.prev while n do - local id = getid(n) + local id = n.id if id == penalty_code then elseif id == glue_code then - if getsubtype(n) == abovedisplayshortskip_code then + if n.subtype == abovedisplayshortskip_code then return true end else break end - n = getprev(n) + n = n.prev end - n = getnext(head) + n = head.next while n do - local id = getid(n) + local id = n.id if id == penalty_code then elseif id == glue_code then - if getsubtype(n) == belowdisplayshortskip_code then + if n.subtype == belowdisplayshortskip_code then return true end else break end - n = getnext(n) + n = n.next end return false end - -nodes.leftmarginwidth = nodes.vianuts(nuts.leftmarginwidth) -nodes.rightmarginwidth = nodes.vianuts(nuts.rightmarginwidth) -nodes.somespace = nodes.vianuts(nuts.somespace) -nodes.somepenalty = nodes.vianuts(nuts.somepenalty) -nodes.is_display_math = nodes.vianuts(nuts.is_display_math) diff --git a/tex/context/base/node-typ.lua b/tex/context/base/node-typ.lua index 4c33e3199..4a2ef8d49 100644 --- a/tex/context/base/node-typ.lua +++ b/tex/context/base/node-typ.lua @@ -8,38 +8,26 @@ if not modules then modules = { } end modules ['node-typ'] = { -- code has been moved to blob-ini.lua -local typesetters = nodes.typesetters or { } -nodes.typesetters = typesetters +local typesetters = nodes.typesetters or { } +nodes.typesetters = typesetters -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut +local hpack_node_list = nodes.hpack +local vpack_node_list = nodes.vpack +local fast_hpack_list = nodes.fasthpack -local setfield = nuts.setfield -local getfont = nuts.getfont - -local hpack_node_list = nuts.hpack -local vpack_node_list = nuts.vpack -local fast_hpack_list = nuts.fasthpack -local copy_node = nuts.copy - -local nodepool = nuts.pool +local nodepool = nodes.pool local new_glyph = nodepool.glyph local new_glue = nodepool.glue local utfvalues = utf.values -local currentfont = font.current -local fontparameters = fonts.hashes.parameters +local currentfont = font.current +local fontparameters = fonts.hashes.parameters -local function tonodes(str,fontid,spacing,templateglyph) -- quick and dirty +local function tonodes(str,fontid,spacing) -- quick and dirty local head, prev = nil, nil if not fontid then - if templateglyph then - fontid = getfont(templateglyph) - else - fontid = currentfont() - end + fontid = currentfont() end local fp = fontparameters[fontid] local s, p, m @@ -56,10 +44,6 @@ local function tonodes(str,fontid,spacing,templateglyph) -- quick and dirty next = new_glue(s,p,m) spacedone = true end - elseif templateglyph then - next = copy_glyph(templateglyph) - setfield(next,"char",c) - spacedone = false else next = new_glyph(fontid or 1,c) spacedone = false @@ -69,8 +53,8 @@ local function tonodes(str,fontid,spacing,templateglyph) -- quick and dirty elseif not head then head = next else - setfield(prev,"next",next) - setfield(next,"prev",prev) + prev.next = next + next.prev = prev end prev = next end @@ -93,30 +77,17 @@ end local tovpackfast = tovpack -local tnuts = { } -nuts.typesetters = tnuts - -tnuts.tonodes = tonodes -tnuts.tohpack = tohpack -tnuts.tohpackfast = tohpackfast -tnuts.tovpack = tovpack -tnuts.tovpackfast = tovpackfast - -tnuts.hpack = tohpack -- obsolete -tnuts.fast_hpack = tohpackfast -- obsolete -tnuts.vpack = tovpack -- obsolete - -typesetters.tonodes = function(...) local h, b = tonodes (...) return tonode(h), b end -typesetters.tohpack = function(...) local h, b = tohpack (...) return tonode(h), b end -typesetters.tohpackfast = function(...) local h, b = tohpackfast(...) return tonode(h), b end -typesetters.tovpack = function(...) local h, b = tovpack (...) return tonode(h), b end -typesetters.tovpackfast = function(...) local h, b = tovpackfast(...) return tonode(h), b end +typesetters.tonodes = tonodes +typesetters.tohpack = tohpack +typesetters.tohpackfast = tohpackfast +typesetters.tovpack = tovpack +typesetters.tovpackfast = tovpackfast -typesetters.hpack = typesetters.tohpack -- obsolete -typesetters.fast_hpack = typesetters.tofasthpack -- obsolete -typesetters.vpack = typesetters.tovpack -- obsolete +typesetters.hpack = tohpack +typesetters.fast_hpack = tohpackfast +typesetters.vpack = tovpack -- node.write(nodes.typestters.hpack("Hello World!")) -- node.write(nodes.typestters.hpack("Hello World!",1,100*1024*10)) -string.tonodes = function(...) return tonode(tonodes(...)) end -- quite convenient +string.tonodes = tonodes -- quite convenient diff --git a/tex/context/base/pack-rul.lua b/tex/context/base/pack-rul.lua index c8ed0722b..329ea63b8 100644 --- a/tex/context/base/pack-rul.lua +++ b/tex/context/base/pack-rul.lua @@ -21,25 +21,15 @@ local line_code = nodes.listcodes.line local texsetdimen = tex.setdimen local texsetcount = tex.setcount - -local nuts = nodes.nuts - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getlist = nuts.getlist -local getsubtype = nuts.getsubtype -local getbox = nuts.getbox - -local hpack = nuts.hpack -local free = nuts.free -local copy = nuts.copy_list -local traverse_id = nuts.traverse_id -local node_dimensions = nuts.dimensions +local texgetbox = tex.getbox +local hpack = nodes.hpack +local free = nodes.free +local copy = nodes.copy_list +local traverse_id = nodes.traverse_id +local node_dimensions = nodes.dimensions function commands.doreshapeframedbox(n) - local box = getbox(n) + local box = texgetbox(n) local noflines = 0 local firstheight = nil local lastdepth = nil @@ -48,27 +38,27 @@ function commands.doreshapeframedbox(n) local maxwidth = 0 local totalwidth = 0 local averagewidth = 0 - local boxwidth = getfield(box,"width") + local boxwidth = box.width if boxwidth ~= 0 then -- and h.subtype == vlist_code - local list = getlist(box) + local list = box.list if list then local function check(n,repack) if not firstheight then - firstheight = getfield(n,"height") + firstheight = n.height end - lastdepth = getfield(n,"depth") + lastdepth = n.depth noflines = noflines + 1 - local l = getlist(n) + local l = n.list if l then if repack then - local subtype = getsubtype(n) + local subtype = n.subtype if subtype == box_code or subtype == line_code then - lastlinelength = node_dimensions(l,getfield(n,"dir")) -- used to be: hpack(copy(l)).width + lastlinelength = node_dimensions(l,n.dir) -- used to be: hpack(copy(l)).width else - lastlinelength = getfield(n,"width") + lastlinelength = n.width end else - lastlinelength = getfield(n,"width") + lastlinelength = n.width end if lastlinelength > maxwidth then maxwidth = lastlinelength @@ -94,27 +84,28 @@ function commands.doreshapeframedbox(n) elseif maxwidth ~= 0 then if hdone then for h in traverse_id(hlist_code,list) do - local l = getlist(h) + local l = h.list if l then - local subtype = getsubtype(h) + local subtype = h.subtype if subtype == box_code or subtype == line_code then - l = hpack(l,maxwidth,'exactly',getfield(h,"dir")) -- multiple return values - setfield(h,"list",l) - setfield(h,"shift",0) -- needed for display math, so no width check possible + h.list = hpack(l,maxwidth,'exactly',h.dir) + h.shift = 0 -- needed for display math end - setfield(h,"width",maxwidth) + h.width = maxwidth end end + box.width = maxwidth -- moved + averagewidth = noflines > 0 and totalwidth/noflines or 0 end -- if vdone then -- for v in traverse_id(vlist_code,list) do - -- local width = getfield(n,"width") + -- local width = n.width -- if width > maxwidth then - -- setfield(v,"width",maxwidth) + -- v.width = maxwidth -- end -- end -- end - setfield(box,"width",maxwidth) + box.width = maxwidth averagewidth = noflines > 0 and totalwidth/noflines or 0 end end @@ -128,18 +119,18 @@ function commands.doreshapeframedbox(n) end function commands.doanalyzeframedbox(n) - local box = getbox(n) + local box = texgetbox(n) local noflines = 0 local firstheight = nil local lastdepth = nil - if getfield(box,"width") ~= 0 then - local list = getlist(box) + if box.width ~= 0 then + local list = box.list if list then local function check(n) if not firstheight then - firstheight = getfield(n,"height") + firstheight = n.height end - lastdepth = getfield(n,"depth") + lastdepth = n.depth noflines = noflines + 1 end for h in traverse_id(hlist_code,list) do diff --git a/tex/context/base/pack-rul.mkiv b/tex/context/base/pack-rul.mkiv index 8fcf8f548..377d39499 100644 --- a/tex/context/base/pack-rul.mkiv +++ b/tex/context/base/pack-rul.mkiv @@ -2564,25 +2564,10 @@ \inheritedframedtextframed\bgroup \let\\=\endgraf \framedtextparameter\c!inner % oud spul - \edef\p_framed_text_depthcorrection{\framedtextparameter\c!depthcorrection}% - \ifx\p_framed_text_depthcorrection\v!on - \pack_framed_text_start_depth_correction - \else - \bgroup - \fi -\vskip-\strutdp % brrr why is this needed ... needs to be sorted out, see testcase 1 + \doif{\framedtextparameter\c!depthcorrection}\v!on\pack_framed_text_start_depth_correction \doinhibitblank \setupindenting[\framedtextparameter\c!indenting]% - \useframedtextstyleandcolor\c!style\c!color - \ignorespaces} - -% testcase 1: -% -% \showstruts -% \startframedtext[align={normal,tolerant},offset=0pt] \input tufte \stopframedtext -% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \input tufte \stopframedtext -% \startframedtext[align={normal,tolerant},offset=0pt,depthcorrection=off] \inframed{x} \stopframedtext -% \framed[align={normal,tolerant},offset=0pt]{\input tufte } + \useframedtextstyleandcolor\c!style\c!color} %D The \type {none} option is handy for nested usage, as in the presentation %D styles, where we don't want interference. @@ -2592,11 +2577,7 @@ \unexpanded\def\pack_framed_text_stop % no \baselinecorrection, see faq docs {\endgraf \removelastskip - \ifx\p_framed_text_depthcorrection\v!on - \pack_framed_text_stop_depth_correction - \else - \egroup - \fi + \doif{\framedtextparameter\c!depthcorrection}\v!on\pack_framed_text_stop_depth_correction \stopboxedcontent \ifconditional\c_framed_text_location_none \egroup diff --git a/tex/context/base/page-brk.mkiv b/tex/context/base/page-brk.mkiv index 11dc04bfd..cc9a9b4d2 100644 --- a/tex/context/base/page-brk.mkiv +++ b/tex/context/base/page-brk.mkiv @@ -316,204 +316,75 @@ %D Test page breaks. -% \newdimen \d_page_tests_test -% \newconstant\c_page_tests_mode +\newdimen \d_page_tests_test +\newconstant\c_page_tests_mode -\newconstant\testpagemethod % old -\newconstant\testpagetrigger % old +\newconstant\testpagemethod % todo: \testnewpage[method=,lines=,voffset=] +\newconstant\testpagetrigger -% \unexpanded\def\testpage {\c_page_tests_mode\plusone \dodoubleempty\page_tests_test} % -% \unexpanded\def\testpageonly{\c_page_tests_mode\plustwo \dodoubleempty\page_tests_test} % no penalties added to the mvl -% \unexpanded\def\testpagesync{\c_page_tests_mode\plusthree\dodoubleempty\page_tests_test} % force sync -% -% \def\page_tests_test[#1][#2]% don't change, only add more methods -% {\relax % needed before \if -% \ifconditional\c_page_breaks_enabled -% % new from here -% \ifcase\testpagetrigger -% \endgraf -% \or\ifvmode -% \dosomebreak\allowbreak -% \else % indeed? -% \vadjust{\allowbreak}% -% \endgraf -% \fi\fi -% % till here -% \ifdim\pagegoal<\maxdimen \relax -% \ifdim\pagetotal<\pagegoal \relax -% \d_page_tests_test\dimexpr -% #1\lineheight -% +\pagetotal -% \ifdim\lastskip<\parskip+\parskip\fi -% \ifsecondargument+#2\fi -% \relax -% \ifcase\testpagemethod -% \ifdim\d_page_tests_test>.99\pagegoal -% \penalty-\plustenthousand -% \fi -% \or -% \ifdim\dimexpr\d_page_tests_test-\pagegoal\relax>-\lineheight -% \penalty-\plustenthousand -% \fi -% \or -% \getnoflines\pagegoal -% \ifdim\dimexpr\d_page_tests_test-\noflines\lineheight\relax>-\lineheight -% \penalty-\plustenthousand -% \fi -% \or % same as 0 but more accurate -% \ifdim\dimexpr\d_page_tests_test-10\scaledpoint\relax>\pagegoal -% \penalty-\plustenthousand -% \fi -% \fi -% \else\ifnum\c_page_tests_mode=\plusthree -% \page_tests_flush_so_far -% \fi\fi -% \else\ifnum\c_page_tests_mode=\plusone -% \goodbreak -% \fi\fi -% \else -% \endgraf -% \fi} -% -% \def\page_tests_flush_so_far -% {\endgraf -% \ifdim\pagetotal>\pagegoal -% \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal -% \goodbreak -% \else -% \page -% \fi -% \fi} - -\installcorenamespace {pagechecker} -\installcorenamespace {pagecheckermethod} - -\installcommandhandler \??pagechecker {pagechecker} \??pagechecker - -\setuppagechecker - [\c!method=1, - \c!before=, - \c!after=, - \c!inbetween=, - \c!lines=\plusthree, - \c!offset=\zeropoint] - -\def\page_check_amount - {\dimexpr - \pagecheckerparameter\c!lines\lineheight - +\pagetotal - \ifdim\lastskip<\parskip+\parskip\fi - +\pagecheckerparameter\c!offset - \relax} - -\unexpanded\def\checkpage - {\dodoubleempty\page_check} - -\def\page_check[#1][#2]% +\unexpanded\def\testpage {\c_page_tests_mode\plusone \dodoubleempty\page_tests_test} % +\unexpanded\def\testpageonly{\c_page_tests_mode\plustwo \dodoubleempty\page_tests_test} % no penalties added to the mvl +\unexpanded\def\testpagesync{\c_page_tests_mode\plusthree\dodoubleempty\page_tests_test} % force sync + +\def\page_tests_test[#1][#2]% don't change, only add more methods {\relax % needed before \if - \endgraf \ifconditional\c_page_breaks_enabled - \begingroup - \edef\currentpagechecker{#1}% - \ifsecondargument\setupcurrentpagechecker[#2]\fi - \csname\??pagecheckermethod\pagecheckerparameter\c!method\endcsname - \endgroup - \fi} - -\setvalue{\??pagecheckermethod 0}% - {\ifdim\pagegoal<\maxdimen \relax - \ifdim\pagetotal<\pagegoal \relax - \ifdim\page_check_amount>.99\pagegoal - \pagecheckerparameter\c!before - \penalty-\plustenthousand - \pagecheckerparameter\c!after - \else - \pagecheckerparameter\c!inbetween - \fi - \else - \pagecheckerparameter\c!inbetween - \fi - \else - \pagecheckerparameter\c!inbetween - \fi} - -\setvalue{\??pagecheckermethod 1}% - {\ifdim\pagegoal<\maxdimen \relax - \ifdim\pagetotal<\pagegoal \relax - \ifdim\dimexpr\page_check_amount-\pagegoal\relax>-\lineheight - \pagecheckerparameter\c!before - \penalty-\plustenthousand - \pagecheckerparameter\c!after - \else - \pagecheckerparameter\c!inbetween - \fi - \else - \pagecheckerparameter\c!inbetween - \fi - \else - \goodbreak - \pagecheckerparameter\c!inbetween - \fi} - -\setvalue{\??pagecheckermethod 2}% - {\ifdim\pagegoal<\maxdimen \relax - \ifdim\pagetotal<\pagegoal \relax - \getnoflines\pagegoal - \ifdim\dimexpr\page_check_amount-\noflines\lineheight\relax>-\lineheight - \pagecheckparameter\c!before - \penalty-\plustenthousand - \pagecheckerparameter\c!after - \else - \pagecheckerparameter\c!inbetween - \fi - \else - \pagecheckerparameter\c!inbetween - \fi + % new from here + \ifcase\testpagetrigger + \endgraf + \or\ifvmode + \dosomebreak\allowbreak + \else % indeed? + \vadjust{\allowbreak}% + \endgraf + \fi\fi + % till here + \ifdim\pagegoal<\maxdimen \relax + \ifdim\pagetotal<\pagegoal \relax + \d_page_tests_test\dimexpr + #1\lineheight + +\pagetotal + \ifdim\lastskip<\parskip+\parskip\fi + \ifsecondargument+#2\fi + \relax + \ifcase\testpagemethod + \ifdim\d_page_tests_test>.99\pagegoal + \penalty-\plustenthousand + \fi + \or + \ifdim\dimexpr\d_page_tests_test-\pagegoal\relax>-\lineheight + \penalty-\plustenthousand + \fi + \or + \getnoflines\pagegoal + \ifdim\dimexpr\d_page_tests_test-\noflines\lineheight\relax>-\lineheight + \penalty-\plustenthousand + \fi + \or % same as 0 but more accurate + \ifdim\dimexpr\d_page_tests_test-10\scaledpoint\relax>\pagegoal + \penalty-\plustenthousand + \fi + \fi + \else\ifnum\c_page_tests_mode=\plusthree + \page_tests_flush_so_far + \fi\fi + \else\ifnum\c_page_tests_mode=\plusone + \goodbreak + \fi\fi \else - \pagecheckerparameter\c!inbetween + \endgraf \fi} -\setvalue{\??pagecheckermethod 3}% - {\ifdim\pagegoal<\maxdimen \relax - \ifdim\pagetotal<\pagegoal \relax - \ifdim\dimexpr\page_check_amount-10\scaledpoint\relax>\pagegoal - \pagecheckerparameter\c!before - \penalty-\plustenthousand - \pagecheckerparameter\c!after - \else - \pagecheckerparameter\c!inbetween - \fi +\def\page_tests_flush_so_far + {\endgraf + \ifdim\pagetotal>\pagegoal + \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal + \goodbreak \else - \ifdim\pagetotal>\pagegoal - \ifdim\dimexpr\pagetotal-\pageshrink\relax>\pagegoal - \goodbreak - \pagecheckerparameter\c!inbetween - \else - \pagecheckerparameter\c!before - \page - \pagecheckerparameter\c!after - \fi - \else - \pagecheckerparameter\c!inbetween - \fi + \page \fi - \else - \pagecheckerparameter\c!inbetween \fi} -\definepagechecker[\s!unknown:0] [\c!method=0,\c!before=,\c!after=,\c!inbetween=] -\definepagechecker[\s!unknown:1][\s!unknown:0][\c!method=1] -\definepagechecker[\s!unknown:2][\s!unknown:0][\c!method=2] -\definepagechecker[\s!unknown:3][\s!unknown:0][\c!method=3] - -\def\page_tests_test_a[#1][#2]{\normalexpanded{\checkpage[\s!unknown:1][\c!lines=#1,\c!offset=\ifsecondargument#2\else\zeropoint\fi]}} -\def\page_tests_test_b[#1][#2]{\normalexpanded{\checkpage[\s!unknown:2][\c!lines=#1,\c!offset=\ifsecondargument#2\else\zeropoint\fi]}} -\def\page_tests_test_c[#1][#2]{\normalexpanded{\checkpage[\s!unknown:3][\c!lines=#1,\c!offset=\ifsecondargument#2\else\zeropoint\fi]}} - -\unexpanded\def\testpage {\dodoubleempty\page_tests_test_a} % -\unexpanded\def\testpageonly{\dodoubleempty\page_tests_test_b} % no penalties added to the mvl -\unexpanded\def\testpagesync{\dodoubleempty\page_tests_test_c} % force sync - %D Test column breaks. \unexpanded\def\testcolumn diff --git a/tex/context/base/page-lay.mkiv b/tex/context/base/page-lay.mkiv index 19f237242..81eb0423c 100644 --- a/tex/context/base/page-lay.mkiv +++ b/tex/context/base/page-lay.mkiv @@ -1026,12 +1026,12 @@ \unexpanded\def\startlayout[#1]% {\page - \globalpushmacro\currentlayout + \pushmacro\currentlayout \doiflayoutdefinedelse{#1}{\setuplayout[#1]}\donothing} % {\setuplayout[\currentlayout]}} \unexpanded\def\stoplayout {\page - \globalpopmacro\currentlayout + \popmacro\currentlayout \setuplayout[\currentlayout]} % NOG EENS NAGAAN WANNEER NU GLOBAL EN WANNEER NIET @@ -1275,7 +1275,7 @@ {\globalpopmacro\currentlayout \globalpopmacro\page_paper_restore \page_paper_restore - \setuplayout[\currentlayout]\relax} % explicit ! + \setuplayout\relax} %D \macros %D {showprint, showframe, showlayout, showsetups} diff --git a/tex/context/base/page-lin.lua b/tex/context/base/page-lin.lua index 66b7e4684..7e8e9ad8a 100644 --- a/tex/context/base/page-lin.lua +++ b/tex/context/base/page-lin.lua @@ -8,35 +8,31 @@ if not modules then modules = { } end modules ['page-lin'] = { -- experimental -> will become builders --- if there is demand for it, we can support multiple numbering streams --- and use more than one attibute +local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end) -local next, tonumber = next, tonumber +local report_lines = logs.reporter("lines") -local trace_numbers = false trackers.register("lines.numbers", function(v) trace_numbers = v end) +local attributes, nodes, node, context = attributes, nodes, node, context -local report_lines = logs.reporter("lines") +nodes.lines = nodes.lines or { } +local lines = nodes.lines -local attributes = attributes -local nodes = nodes -local context = context +lines.data = lines.data or { } -- start step tag +local data = lines.data +local last = #data -nodes.lines = nodes.lines or { } -local lines = nodes.lines +local texgetbox = tex.getbox -lines.data = lines.data or { } -- start step tag -local data = lines.data -local last = #data +lines.scratchbox = lines.scratchbox or 0 -lines.scratchbox = lines.scratchbox or 0 +local leftmarginwidth = nodes.leftmarginwidth -storage.register("lines/data", data, "nodes.lines.data") +storage.register("lines/data", lines.data, "nodes.lines.data") -local variables = interfaces.variables +-- if there is demand for it, we can support multiple numbering streams +-- and use more than one attibute -local v_next = variables.next -local v_page = variables.page -local v_no = variables.no +local variables = interfaces.variables local nodecodes = nodes.nodecodes @@ -53,25 +49,12 @@ local current_list = { } local cross_references = { } local chunksize = 250 -- not used in boxed -local nuts = nodes.nuts - -local getid = nuts.getid -local getnext = nuts.getnext -local getattr = nuts.getattr -local getlist = nuts.getlist -local getbox = nuts.getbox -local getfield = nuts.getfield - -local setfield = nuts.setfield - -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse -local copy_node = nuts.copy -local hpack_node = nuts.hpack -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before -local is_display_math = nuts.is_display_math -local leftmarginwidth = nuts.leftmarginwidth +local traverse_id = node.traverse_id +local traverse = node.traverse +local copy_node = node.copy +local hpack_node = node.hpack +local insert_node_after = node.insert_after +local insert_node_before = node.insert_before -- cross referencing @@ -84,16 +67,16 @@ end local function resolve(n,m) -- we can now check the 'line' flag (todo) while n do - local id = getid(n) + local id = n.id if id == whatsit_code then -- why whatsit - local a = getattr(n,a_linereference) + local a = n[a_linereference] if a then cross_references[a] = m end elseif id == hlist_code or id == vlist_code then - resolve(getlist(n),m) + resolve(n.list,m) end - n = getnext(n) + n = n.next end end @@ -182,20 +165,20 @@ local function check_number(n,a,skip,sameline) if sameline then skipflag = 0 if trace_numbers then - report_lines("skipping broken line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no) + report_lines("skipping broken line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or "no") end elseif not skip and s % d.step == 0 then skipflag, d.start = 1, s + 1 -- (d.step or 1) if trace_numbers then - report_lines("making number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no) + report_lines("making number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or "no") end else skipflag, d.start = 0, s + 1 -- (d.step or 1) if trace_numbers then - report_lines("skipping line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or v_no) + report_lines("skipping line number %s for setup %a: %s (%s)",#current_list,a,s,d.continue or "no") end end - context.makelinenumber(tag,skipflag,s,getfield(n,"shift"),getfield(n,"width"),leftmarginwidth(getlist(n)),getfield(n,"dir")) + context.makelinenumber(tag,skipflag,s,n.shift,n.width,leftmarginwidth(n.list),n.dir) end end @@ -206,26 +189,26 @@ end local function identify(list) if list then for n in traverse_id(hlist_code,list) do - if getattr(n,a_linenumber) then + if n[a_linenumber] then return list end end local n = list while n do - local id = getid(n) + local id = n.id if id == hlist_code or id == vlist_code then - local ok = identify(getlist(n)) + local ok = identify(n.list) if ok then return ok end end - n = getnext(n) + n = n.next end end end function boxed.stage_zero(n) - return identify(getlist(getbox(n))) + return identify(texgetbox(n).list) end -- reset ranges per page @@ -234,39 +217,39 @@ end function boxed.stage_one(n,nested) current_list = { } - local box = getbox(n) + local box = texgetbox(n) if box then - local list = getlist(box) + local list = box.list if nested then list = identify(list) end local last_a, last_v, skip = nil, -1, false for n in traverse_id(hlist_code,list) do -- attr test here and quit as soon as zero found - if getfield(n,"height") == 0 and getfield(n,"depth") == 0 then + if n.height == 0 and n.depth == 0 then -- skip funny hlists -- todo: check line subtype else - local list = getlist(n) - local a = getattr(list,a_linenumber) + local list = n.list + local a = list[a_linenumber] if a and a > 0 then if last_a ~= a then local da = data[a] local ma = da.method - if ma == v_next then + if ma == variables.next then skip = true - elseif ma == v_page then + elseif ma == variables.page then da.start = 1 -- eventually we will have a normal counter end last_a = a if trace_numbers then - report_lines("starting line number range %s: start %s, continue %s",a,da.start,da.continue or v_no) + report_lines("starting line number range %s: start %s, continue",a,da.start,da.continue or "no") end end - if getattr(n,a_displaymath) then - if is_display_math(n) then + if n[a_displaymath] then + if nodes.is_display_math(n) then check_number(n,a,skip) end else - local v = getattr(list,a_verbatimline) + local v = list[a_verbatimline] if not v or v ~= last_v then last_v = v check_number(n,a,skip) @@ -285,7 +268,7 @@ function boxed.stage_two(n,m) if #current_list > 0 then m = m or lines.scratchbox local t, tn = { }, 0 - for l in traverse_id(hlist_code,getlist(getbox(m))) do + for l in traverse_id(hlist_code,texgetbox(m).list) do tn = tn + 1 t[tn] = copy_node(l) end @@ -293,8 +276,7 @@ function boxed.stage_two(n,m) local li = current_list[i] local n, m, ti = li[1], li[2], t[i] if ti then - setfield(ti,"next",getlist(n)) - setfield(n,"list",ti) + ti.next, n.list = n.list, ti resolve(n,m) else report_lines("error in linenumbering (1)") diff --git a/tex/context/base/page-mak.mkvi b/tex/context/base/page-mak.mkvi index c910f281d..71af520a1 100644 --- a/tex/context/base/page-mak.mkvi +++ b/tex/context/base/page-mak.mkvi @@ -91,60 +91,13 @@ \def\page_makeup_start_yes[#name]% [#settings]% {\doifelsecommandhandler\??makeup{#name}\page_makeup_start_indeed\page_makeup_start_nop[#name]}% -% case 1: -% -% \setuplayout[height=5cm] -% -% case 2: -% -% \definelayout[crap][height=10cm] -% \definelayout[standard][crap] -% -% case 3: -% -% \setuplayout[standard][height=15cm] -% -% case 4: -% -% \definelayout[whatever][height=2cm] -% \setuplayout[whatever] - \def\page_makeup_start_indeed[#name][#settings]% - {% the next grouping hack is somewhat messy: - \begingroup - % we need to figure out the current layout - \xdef\m_page_makeup_name{#name}% - \let\currentmakeup\m_page_makeup_name - \let\currentlayout\m_page_makeup_name - \xdef\m_page_makeup_layout_parent{\layoutparameter\s!parent}% - \setupcurrentmakeup[#settings]% - \edef\p_page{\makeupparameter\c!page}% - \ifx\p_page\empty - \endgroup - \page % new, so best not have dangling mess here like references (we could capture then and flush embedded) - \else\ifx\p_page\v!no - % nothing - \endgroup - \else - \endgroup - \page[\p_page]% - \fi\fi - % some dirty trickery (sorry) for determining if we have - % - a layout definition at all - % - inherit from the parent of that definition - % - inherit from the current layout otherwise - \ifx\m_page_makeup_name\currentlayout - % we already use the layout - \else\ifx\m_page_makeup_layout_parent\??layout - % we inherit from the current layout - \normalexpanded{\setuplayout[#name][\s!parent=\??layout\currentlayout]}% is remembered but checked later anyway - % \else - % we have an inherited layout - \fi\fi + {\doifelsenothing{\namedmakeupparameter{#name}\c!page} + {\page}% new, so best not have dangling mess here like references (we could capture then and flush embedded) + {\page[\namedmakeupparameter{#name}\c!page]}% \startlayout[#name]% includes \page \bgroup - %\edef\currentmakeup{#name}% - \let\currentmakeup\m_page_makeup_name + \edef\currentmakeup{#name}% \setupcurrentmakeup[#settings]% \setsystemmode\v!makeup \the\t_page_makeup_every_setup @@ -184,12 +137,7 @@ \fi \fi \strc_pagenumbers_page_state_pop % new \egroup - \stoplayout % includes \page - \ifx\m_page_makeup_name\currentlayout - \else\ifx\m_page_makeup_layout_parent\??layout - \normalexpanded{\setuplayout[\m_page_makeup_name][\s!parent=\??layout]}% is remembered but checked later anyway - % \else - \fi\fi} + \stoplayout} % includes \page \setvalue{\??makeupdoublesided\v!yes}% {\emptyhbox @@ -236,7 +184,6 @@ \c!headerstate=\v!stop, \c!footerstate=\v!stop, \c!pagestate=\v!stop] % in manual ! ! ! -% \c!pagestate=\v!start] \definemakeup [\v!standard] diff --git a/tex/context/base/page-mix.lua b/tex/context/base/page-mix.lua index 30a1fdccd..7d13d9e4e 100644 --- a/tex/context/base/page-mix.lua +++ b/tex/context/base/page-mix.lua @@ -15,73 +15,46 @@ if not modules then modules = { } end modules ["page-mix"] = { local concat = table.concat +local nodecodes = nodes.nodecodes +local gluecodes = nodes.gluecodes +local nodepool = nodes.pool + +local hlist_code = nodecodes.hlist +local vlist_code = nodecodes.vlist +local kern_code = nodecodes.kern +local glue_code = nodecodes.glue +local penalty_code = nodecodes.penalty +local insert_code = nodecodes.ins +local mark_code = nodecodes.mark + +local new_hlist = nodepool.hlist +local new_vlist = nodepool.vlist +local new_glue = nodepool.glue + +local hpack = node.hpack +local vpack = node.vpack +local freenode = node.free +local concatnodes = nodes.concat + +local texgetbox = tex.getbox +local texsetbox = tex.setbox +local texgetskip = tex.getskip + +local points = number.points + +local settings_to_hash = utilities.parsers.settings_to_hash + +local variables = interfaces.variables +local v_yes = variables.yes +local v_global = variables["global"] +local v_local = variables["local"] +local v_columns = variables.columns + local trace_state = false trackers.register("mixedcolumns.trace", function(v) trace_state = v end) local trace_detail = false trackers.register("mixedcolumns.detail", function(v) trace_detail = v end) local report_state = logs.reporter("mixed columns") -local nodecodes = nodes.nodecodes -local gluecodes = nodes.gluecodes - -local hlist_code = nodecodes.hlist -local vlist_code = nodecodes.vlist -local kern_code = nodecodes.kern -local glue_code = nodecodes.glue -local penalty_code = nodecodes.penalty -local insert_code = nodecodes.ins -local mark_code = nodecodes.mark -local rule_code = nodecodes.rule - -local topskip_code = gluecodes.topskip -local lineskip_code = gluecodes.lineskip -local baselineskip_code = gluecodes.baselineskip -local userskip_code = gluecodes.userskip - -local nuts = nodes.nuts -local tonode = nuts.tonode -local nodetostring = nuts.tostring -local listtoutf = nodes.listtoutf - -local hpack = nuts.hpack -local vpack = nuts.vpack -local freenode = nuts.free -local concatnodes = nuts.concat -local slidenodes = nuts.slide -- ok here as we mess with prev links intermediately -local traversenodes = nuts.traverse - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getsubtype = nuts.getsubtype -local getbox = nuts.getbox -local setbox = nuts.setbox -local getskip = nuts.getskip -local getattribute = nuts.getattribute - -local nodepool = nuts.pool - -local new_hlist = nodepool.hlist -local new_vlist = nodepool.vlist -local new_glue = nodepool.glue - -local points = number.points - -local settings_to_hash = utilities.parsers.settings_to_hash - -local variables = interfaces.variables -local v_yes = variables.yes -local v_global = variables["global"] -local v_local = variables["local"] -local v_columns = variables.columns -local v_fixed = variables.fixed -local v_auto = variables.auto -local v_none = variables.none -local v_more = variables.more -local v_less = variables.less - pagebuilders = pagebuilders or { } pagebuilders.mixedcolumns = pagebuilders.mixedcolumns or { } local mixedcolumns = pagebuilders.mixedcolumns @@ -104,13 +77,13 @@ local function collectinserts(result,nxt,nxtid) local inserts, currentskips, nextskips, inserttotal = { }, 0, 0, 0 while nxt do if nxtid == insert_code then - inserttotal = inserttotal + getfield(nxt,"height") + getfield(nxt,"depth") - local s = getsubtype(nxt) + inserttotal = inserttotal + nxt.height + nxt.depth + local s = nxt.subtype local c = inserts[s] if not c then c = { } inserts[s] = c - local width = getfield(getskip(s),"width") + local width = texgetskip(s).width if not result.inserts[s] then currentskips = currentskips + width end @@ -127,9 +100,9 @@ local function collectinserts(result,nxt,nxtid) else break end - nxt = getnext(nxt) + nxt = nxt.next if nxt then - nxtid = getid(nxt) + nxtid = nxt.id else break end @@ -155,30 +128,30 @@ end local function discardtopglue(current,discarded) local size = 0 while current do - local id = getid(current) + local id = current.id if id == glue_code then - size = size + getfield(getfield(current,"spec"),"width") + size = size + current.spec.width discarded[#discarded+1] = current - current = getnext(current) + current = current.next elseif id == penalty_code then - if getfield(current,"penalty") == forcedbreak then + if current.penalty == forcedbreak then discarded[#discarded+1] = current - current = getnext(current) - while current and getid(current) == glue_code do - size = size + getfield(getfield(current,"spec"),"width") + current = current.next + while current and current.id == glue_code do + size = size + current.spec.width discarded[#discarded+1] = current - current = getnext(current) + current = current.next end else discarded[#discarded+1] = current - current = getnext(current) + current = current.next end else break end end if current then - setfield(current,"prev",nil) -- prevent look back + current.prev = nil end return current, size end @@ -189,13 +162,13 @@ local function stripbottomglue(results,discarded) local r = results[i] local t = r.tail while t and t ~= r.head do - local prev = getprev(t) + local prev = t.prev if not prev then break end - local id = getid(t) + local id = t.id if id == penalty_code then - if getfield(t,"penalty") == forcedbreak then + if t.penalty == forcedbreak then break else discarded[#discarded+1] = t @@ -204,7 +177,7 @@ local function stripbottomglue(results,discarded) end elseif id == glue_code then discarded[#discarded+1] = t - local width = getfield(getfield(t,"spec"),"width") + local width = t.spec.width if trace_state then report_state("columns %s, discarded bottom glue %p",i,width) end @@ -228,21 +201,20 @@ local function setsplit(specification) -- a rather large function report_state("fatal error, no box") return end - local list = getbox(box) + local list = texgetbox(box) if not list then report_state("fatal error, no list") return end - local head = getlist(list) or specification.originalhead + local head = list.head or specification.originalhead if not head then report_state("fatal error, no head") return end - slidenodes(head) -- we can have set prev's to nil to prevent backtracking local discarded = { } local originalhead = head - local originalwidth = specification.originalwidth or getfield(list,"width") - local originalheight = specification.originalheight or getfield(list,"height") + local originalwidth = specification.originalwidth or list.width + local originalheight = specification.originalheight or list.height local current = head local skipped = 0 local height = 0 @@ -305,20 +277,20 @@ local function setsplit(specification) -- a rather large function local current = start -- first skip over glue and penalty while current do - local id = getid(current) + local id = current.id if id == glue_code or id == penalty_code then - current = getprev(current) + current = current.prev else break end end -- then skip over content while current do - local id = getid(current) + local id = current.id if id == glue_code or id == penalty_code then break else - current = getprev(current) + current = current.prev end end if not current then @@ -352,7 +324,7 @@ local function setsplit(specification) -- a rather large function if current == head then result.tail = head else - result.tail = getprev(current) + result.tail = current.prev end result.height = height result.depth = depth @@ -372,9 +344,6 @@ local function setsplit(specification) -- a rather large function report_state("setting collector to column %s",column) end current, skipped = discardtopglue(current,discarded) - if trace_detail and skipped ~= 0 then - report_state("check > column 1, discarded %p",skipped) - end head = current return true, skipped end @@ -397,7 +366,7 @@ local function setsplit(specification) -- a rather large function end end if trace_detail then - report_state("%-7s > column %s, delta %p, threshold %p, advance %p, total %p, target %p => %a (height %p, depth %p, skip %p)", + report_state("%-7s > column %s, delta %p, threshold %p, advance %p, total %p, target %p, discarded %p => %a (height %p, depth %p, skip %p)", where,curcol,delta,threshold,advance,total,target,state,skipped,height,depth,skip) end return state, skipped @@ -418,7 +387,7 @@ local function setsplit(specification) -- a rather large function head = current local function process_skip(current,nxt) - local advance = getfield(getfield(current,"spec"),"width") + local advance = current.spec.width if advance ~= 0 then local state, skipped = checked(advance,"glue") if trace_state then @@ -442,7 +411,7 @@ local function setsplit(specification) -- a rather large function end local function process_kern(current,nxt) - local advance = getfield(current,"kern") + local advance = current.kern if advance ~= 0 then local state, skipped = checked(advance,"kern") if trace_state then @@ -465,10 +434,10 @@ local function setsplit(specification) -- a rather large function local function process_rule(current,nxt) -- simple variant of h|vlist - local advance = getfield(current,"height") -- + getfield(current,"depth") + local advance = current.height -- + current.depth local state, skipped = checked(advance+currentskips,"rule") if trace_state then - report_state("%-7s > column %s, state %a, rule, advance %p, height %p","rule",column,state,advance,inserttotal,height) + report_state("%-7s > column %s, state %a, rule, advance %p, height %p","line",column,state,advance,inserttotal,height) if skipped ~= 0 then report_state("%-7s > column %s, discarded %p","rule",column,skipped) end @@ -482,7 +451,7 @@ local function setsplit(specification) -- a rather large function else height = height + currentskips end - depth = getfield(current,"depth") + depth = current.depth skip = 0 end @@ -493,12 +462,12 @@ local function setsplit(specification) -- a rather large function -- [chapter] [penalty] [section] [penalty] [first line] local function process_penalty(current,nxt) - local penalty = getfield(current,"penalty") + local penalty = current.penalty if penalty == 0 then lastlocked = nil lastcurrent = nil elseif penalty == forcedbreak then - local needed = getattribute(current,a_checkedbreak) + local needed = current[a_checkedbreak] local proceed = not needed or needed == 0 if not proceed then local available = target - height @@ -546,12 +515,12 @@ local function setsplit(specification) -- a rather large function end local function process_list(current,nxt) - local nxtid = nxt and getid(nxt) + local nxtid = nxt and nxt.id line = line + 1 local inserts, currentskips, nextskips, inserttotal = nil, 0, 0, 0 - local advance = getfield(current,"height") -- + getfield(current,"depth") + local advance = current.height -- + current.depth if trace_state then - report_state("%-7s > column %s, content: %s","line",column,listtoutf(getlist(current),true,true)) + report_state("%-7s > column %s, content: %s","line",column,listtoutf(current.list,true,true)) end if nxt and (nxtid == insert_code or nxtid == mark_code) then nxt, inserts, localskips, insertskips, inserttotal = collectinserts(result,nxt,nxtid) @@ -572,7 +541,7 @@ local function setsplit(specification) -- a rather large function else height = height + currentskips end - depth = getfield(current,"depth") + depth = current.depth skip = 0 if inserts then -- so we already collect them ... makes backtracking tricky ... alternatively @@ -586,8 +555,8 @@ local function setsplit(specification) -- a rather large function while current do - local id = getid(current) - local nxt = getnext(current) + local id = current.id + local nxt = current.next backtracked = false @@ -660,7 +629,7 @@ local function setsplit(specification) -- a rather large function specification.overflow = overflow specification.discarded = discarded - setfield(getbox(specification.box),"list",nil) + texgetbox(specification.box).list = nil return specification end @@ -672,12 +641,12 @@ function mixedcolumns.finalize(result) local r = results[i] local h = r.head if h then - setfield(h,"prev",nil) + h.prev = nil local t = r.tail if t then - setfield(t,"next",nil) + t.next = nil else - setfield(h,"next",nil) + h.next = nil r.tail = h end for c, list in next, r.inserts do @@ -686,13 +655,13 @@ function mixedcolumns.finalize(result) local l = list[i] local h = new_hlist() t[i] = h - setfield(h,"list",getfield(l,"head")) - setfield(h,"height",getfield(l,"height")) - setfield(h,"depth",getfield(l,"depth")) - setfield(l,"head",nil) + h.head = l.head + h.height = l.height + h.depth = l.depth + l.head = nil end - setfield(t[1],"prev",nil) -- needs checking - setfield(t[#t],"next",nil) -- needs checking + t[1].prev = nil -- needs checking + t[#t].next = nil -- needs checking r.inserts[c] = t end end @@ -764,13 +733,13 @@ function mixedcolumns.getsplit(result,n) return new_glue(result.originalwidth) end - setfield(h,"prev",nil) -- move up + h.prev = nil -- move up local strutht = result.strutht local strutdp = result.strutdp local lineheight = strutht + strutdp local v = new_vlist() - setfield(v,"list",h) + v.head = h -- local v = vpack(h,"exactly",height) @@ -792,14 +761,14 @@ function mixedcolumns.getsplit(result,n) dp = result.depth end - setfield(v,"width",wd) - setfield(v,"height",ht) - setfield(v,"depth",dp) + v.width = wd + v.height = ht + v.depth = dp if trace_state then - local id = getid(h) + local id = h.id if id == hlist_code then - report_state("flush, column %s, grid %a, width %p, height %p, depth %p, %s: %s",n,grid,wd,ht,dp,"top line",listtoutf(getlist(h))) + report_state("flush, column %s, grid %a, width %p, height %p, depth %p, %s: %s",n,grid,wd,ht,dp,"top line",nodes.toutf(h.list)) else report_state("flush, column %s, grid %a, width %p, height %p, depth %p, %s: %s",n,grid,wd,ht,dp,"head node",nodecodes[id]) end @@ -808,8 +777,8 @@ function mixedcolumns.getsplit(result,n) for c, list in next, r.inserts do local l = concatnodes(list) local b = vpack(l) -- multiple arguments, todo: fastvpack - -- setbox("global",c,b) - setbox(c,b) + -- texsetbox("global",c,b) + texsetbox(c,b) r.inserts[c] = nil end @@ -853,7 +822,7 @@ end function commands.mixgetsplit(n) if result then - context(tonode(mixedcolumns.getsplit(result,n))) + context(mixedcolumns.getsplit(result,n)) end end @@ -865,13 +834,13 @@ end function commands.mixflushrest() if result then - context(tonode(mixedcolumns.getrest(result))) + context(mixedcolumns.getrest(result)) end end function commands.mixflushlist() if result then - context(tonode(mixedcolumns.getlist(result))) + context(mixedcolumns.getlist(result)) end end diff --git a/tex/context/base/page-mix.mkiv b/tex/context/base/page-mix.mkiv index d2bb38ca0..5d1c54a71 100644 --- a/tex/context/base/page-mix.mkiv +++ b/tex/context/base/page-mix.mkiv @@ -517,8 +517,7 @@ %D footnotes. Eventually we will have multiple strategies available. \unexpanded\def\page_mix_routine_construct#1% - {\d_page_mix_max_height\mixedcolumnsparameter\c!maxheight % can have changed due to header=high - \ctxcommand{mixsetsplit { + {\ctxcommand{mixsetsplit { box = \number\b_page_mix_collected, nofcolumns = \number\c_page_mix_n_of_columns, maxheight = \number\d_page_mix_max_height, diff --git a/tex/context/base/page-mul.mkiv b/tex/context/base/page-mul.mkiv index 73d84fe14..a874cd116 100644 --- a/tex/context/base/page-mul.mkiv +++ b/tex/context/base/page-mul.mkiv @@ -1605,11 +1605,9 @@ \else \balancecolumnsfalse \fi - % % this won't work (blocked by check for overloading; too fuzzy anyway) - % \installalign\v!yes {\page_columns_align_option_yes }% \stretchcolumnstrue \inheritcolumnsfalse - % \installalign\v!no {\page_columns_align_option_no }% \stretchcolumnsfalse\inheritcolumnsfalse - % \installalign\v!text{\page_columns_align_option_text}% \stretchcolumnsfalse\inheritcolumnstrue - % % + \installalign\v!yes {\page_columns_align_option_yes }% + \installalign\v!no {\page_columns_align_option_no }% + \installalign\v!text{\page_columns_align_option_text}% \stretchcolumnsfalse \inheritcolumnstrue \edef\p_align{\columnsparameter\c!align}% diff --git a/tex/context/base/page-str.lua b/tex/context/base/page-str.lua index f2ac27cd9..35ce85609 100644 --- a/tex/context/base/page-str.lua +++ b/tex/context/base/page-str.lua @@ -20,7 +20,7 @@ local tasks = nodes.tasks local new_kern = nodepool.kern local new_glyph = nodepool.glyph -local slide_nodelist = node.slide +local find_tail = node.slide local write_node = node.write local free_node = node.free local copy_nodelist = node.copy_list @@ -73,7 +73,7 @@ function streams.collect(head,where) end local last = dana[#dana] if last then - local tail = slide_nodelist(last) + local tail = find_tail(last) tail.next, head.prev = head, tail elseif last == false then dana[#dana] = head @@ -202,7 +202,7 @@ function streams.synchronize(list) -- this is an experiment ! else -- this is not yet ok as we also need to keep an eye on vertical spacing -- so we might need to do some splitting or whatever - local tail = vbox.list and slide_nodelist(vbox.list) + local tail = vbox.list and find_tail(vbox.list) local n, delta = 0, delta_height -- for tracing while delta > 0 do -- we need to add some interline penalties diff --git a/tex/context/base/page-str.mkiv b/tex/context/base/page-str.mkiv index a8fab9c6c..200a71377 100644 --- a/tex/context/base/page-str.mkiv +++ b/tex/context/base/page-str.mkiv @@ -29,6 +29,8 @@ %D %D Remark: marknotes are gone, at least for a while. +\writestatus{loading}{ConTeXt Page Macros / Page Streams} + \registerctxluafile{page-str}{1.001} \unprotect diff --git a/tex/context/base/publ-aut.lua b/tex/context/base/publ-aut.lua deleted file mode 100644 index ba492a93b..000000000 --- a/tex/context/base/publ-aut.lua +++ /dev/null @@ -1,550 +0,0 @@ -if not modules then modules = { } end modules ['publ-aut'] = { - version = 1.001, - comment = "this module part of publication support", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -if not characters then - dofile(resolvers.findfile("char-def.lua")) - dofile(resolvers.findfile("char-ini.lua")) -end - -local context = context -local chardata = characters.data - -local tostring = tostring -local concat = table.concat -local lpeg = lpeg -local utfchar = utf.char - -local publications = publications or { } - -local datasets = publications.datasets or { } -publications.datasets = datasets - -publications.authors = publications.authors or { } -local authors = publications.authors - -local P, C, V, Cs, Ct, lpegmatch, lpegpatterns = lpeg.P, lpeg.C, lpeg.V, lpeg.Cs, lpeg.Ct, lpeg.match, lpeg.patterns - --- local function makesplitter(separator) --- return Ct { "start", --- start = (Cs((V("outer") + (1-separator))^1) + separator^1)^1, --- start = Cs(V("outer")) + (Cs((V("inner") + (1-separator))^1) + separator^1)^1, --- outer = (P("{")/"") * ((V("inner") + P(1-P("}")))^0) * (P("}")/""), --- inner = P("{") * ((V("inner") + P(1-P("}")))^0) * P("}"), --- } --- end - -local space = P(" ") -local comma = P(",") -local firstcharacter = lpegpatterns.utf8byte - --- local andsplitter = lpeg.tsplitat(space^1 * "and" * space^1) --- local commasplitter = lpeg.tsplitat(space^0 * comma * space^0) --- local spacesplitter = lpeg.tsplitat(space^1) - -local p_and = space^1 * "and" * space^1 -local p_comma = space^0 * comma * space^0 -local p_space = space^1 - -local andsplitter = Ct { "start", - start = (Cs((V("inner") + (1-p_and))^1) + p_and)^1, - inner = P("{") * ((V("inner") + P(1-P("}")))^1) * P("}"), -} - -local commasplitter = Ct { "start", - start = Cs(V("outer")) + (Cs((V("inner") + (1-p_comma))^1) + p_comma)^1, - outer = (P("{")/"") * ((V("inner") + P(1-P("}")))^1) * (P("}")/""), - inner = P("{") * ((V("inner") + P(1-P("}")))^1) * P("}"), -} - -local spacesplitter = Ct { "start", - start = Cs(V("outer")) + (Cs((V("inner") + (1-p_space))^1) + p_space)^1, - outer = (P("{")/"") * ((V("inner") + P(1-P("}")))^1) * (P("}")/""), - inner = P("{") * ((V("inner") + P(1-P("}")))^1) * P("}"), -} - -local function is_upper(str) - local first = lpegmatch(firstcharacter,str) - local okay = chardata[first] - return okay and okay.category == "lu" -end - -local cache = { } -- 33% reuse on tugboat.bib -local nofhits = 0 -local nofused = 0 - -local function splitauthorstring(str) - if not str then - return - end - nofused = nofused + 1 - local authors = cache[str] - if authors then - -- hit 1 - -- print("hit 1",author,nofhits,nofused,math.round(100*nofhits/nofused)) - return { authors } -- we assume one author - end - local authors = lpegmatch(andsplitter,str) - for i=1,#authors do - local author = authors[i] - local detail = cache[author] - if detail then - -- hit 2 - -- print("hit 2",author,nofhits,nofused,math.round(100*nofhits/nofused)) - end - if not detail then - local firstnames, vons, surnames, initials, juniors - local split = lpegmatch(commasplitter,author) --- inspect(split) - local n = #split - if n == 1 then - -- First von Last - local words = lpegmatch(spacesplitter,author) - firstnames, vons, surnames = { }, { }, { } - local i, n = 1, #words - while i <= n do - local w = words[i] - if is_upper(w) then - firstnames[#firstnames+1], i = w, i + 1 - else - break - end - end - while i <= n do - local w = words[i] - if is_upper(w) then - break - else - vons[#vons+1], i = w, i + 1 - end - end - if i <= n then - while i <= n do - surnames[#surnames+1], i = words[i], i + 1 - end - elseif #vons == 0 then - surnames[1] = firstnames[#firstnames] - firstnames[#firstnames] = nil - else - -- mess - end - -- safeguard - if #surnames == 0 then - firstnames = { } - vons = { } - surnames = { author } - end - elseif n == 2 then - -- von Last, First - firstnames, vons, surnames = { }, { }, { } - local words = lpegmatch(spacesplitter,split[1]) - local i, n = 1, #words - while i <= n do - local w = words[i] - if is_upper(w) then - break - else - vons[#vons+1], i = w, i + 1 - end - end - while i <= n do - surnames[#surnames+1], i = words[i], i + 1 - end - -- - local words = lpegmatch(spacesplitter,split[2]) - local i, n = 1, #words - while i <= n do - local w = words[i] - if is_upper(w) then - firstnames[#firstnames+1], i = w, i + 1 - else - break - end - end - while i <= n do - vons[#vons+1], i = words[i], i + 1 - end - else - -- von Last, Jr ,First - firstnames = lpegmatch(spacesplitter,split[1]) - juniors = lpegmatch(spacesplitter,split[2]) - surnames = lpegmatch(spacesplitter,split[3]) - if n > 3 then - -- error - end - end - if #surnames == 0 then - surnames[1] = firstnames[#firstnames] - firstnames[#firstnames] = nil - end - if firstnames then - initials = { } - for i=1,#firstnames do - initials[i] = utfchar(lpegmatch(firstcharacter,firstnames[i])) - end - end - detail = { - original = author, - firstnames = firstnames, - vons = vons, - surnames = surnames, - initials = initials, - juniors = juniors, - } - cache[author] = detail - nofhits = nofhits + 1 - end - authors[i] = detail - end - return authors -end - --- local function splitauthors(dataset,tag,field) --- local entries = datasets[dataset] --- local luadata = entries.luadata --- if not luadata then --- return { } --- end --- local entry = luadata[tag] --- if not entry then --- return { } --- end --- return splitauthorstring(entry[field]) --- end - -local function the_initials(initials,symbol) - local t, symbol = { }, symbol or "." - for i=1,#initials do - t[i] = initials[i] .. symbol - end - return t -end - --- authors - -local settings = { } - --- local defaultsettings = { --- firstnamesep = " ", --- vonsep = " ", --- surnamesep = " ", --- juniorsep = " ", --- surnamejuniorsep = ", ", --- juniorjuniorsep = ", ", --- surnamefirstnamesep = ", ", --- surnameinitialsep = ", ", --- namesep = ", ", --- lastnamesep = " and ", --- finalnamesep = " and ", --- etallimit = 1000, --- etaldisplay = 1000, --- etaltext = "", --- } - -local defaultsettings = { - firstnamesep = [[\btxlistvariantparameter{firstnamesep}]], - vonsep = [[\btxlistvariantparameter{vonsep}]], - surnamesep = [[\btxlistvariantparameter{surnamesep}]], - juniorsep = [[\btxlistvariantparameter{juniorsep}]], - surnamejuniorsep = [[\btxlistvariantparameter{surnamejuniorsep}]], - juniorjuniorsep = [[\btxlistvariantparameter{juniorjuniorsep}]], - surnamefirstnamesep = [[\btxlistvariantparameter{surnamefirstnamesep}]], - surnameinitialsep = [[\btxlistvariantparameter{surnameinitialsep}]], - namesep = [[\btxlistvariantparameter{namesep}]], - lastnamesep = [[\btxlistvariantparameter{lastnamesep}]], - finalnamesep = [[\btxlistvariantparameter{finalnamesep}]], - -- - etaltext = [[\btxlistvariantparameter{etaltext}]], - -- - etallimit = 1000, - etaldisplay = 1000, -} - -function authors.setsettings(s) -end - -authors.splitstring = splitauthorstring - --- [firstnames] [firstnamesep] [vons] [vonsep] [surnames] [juniors] [surnamesep] (Taco, von Hoekwater, jr) - -function authors.normal(author,settings) - local firstnames, vons, surnames, juniors = author.firstnames, author.vons, author.surnames, author.juniors - local result, settings = { }, settings or defaultsettings - if firstnames and #firstnames > 0 then - result[#result+1] = concat(firstnames," ") - result[#result+1] = settings.firstnamesep or defaultsettings.firstnamesep - end - if vons and #vons > 0 then - result[#result+1] = concat(vons," ") - result[#result+1] = settings.vonsep or defaultsettings.vonsep - end - if surnames and #surnames > 0 then - result[#result+1] = concat(surnames," ") - if juniors and #juniors > 0 then - result[#result+1] = settings.surnamejuniorsep or defaultsettings.surnamejuniorsep - result[#result+1] = concat(juniors," ") - end - elseif juniors and #juniors > 0 then - result[#result+1] = concat(juniors," ") - end - return concat(result) -end - --- [initials] [initialsep] [vons] [vonsep] [surnames] [juniors] [surnamesep] (T, von Hoekwater, jr) - -function authors.normalshort(author,settings) - local initials, vons, surnames, juniors = author.initials, author.vons, author.surnames, author.juniors - local result, settings = { }, settings or defaultsettings - if initials and #initials > 0 then - result[#result+1] = concat(initials," ") - result[#result+1] = settings.initialsep or defaultsettings.initialsep - end - if vons and #vons > 0 then - result[#result+1] = concat(vons," ") - result[#result+1] = settings.vonsep or defaultsettings.vonsep - end - if surnames and #surnames > 0 then - result[#result+1] = concat(surnames," ") - if juniors and #juniors > 0 then - result[#result+1] = settings.surnamejuniorsep or defaultsettings.surnamejuniorsep - result[#result+1] = concat(juniors," ") - end - elseif juniors and #juniors > 0 then - result[#result+1] = concat(juniors," ") - end - return concat(result) -end - --- vons surnames juniors, firstnames - --- [vons] [vonsep] [surnames] [surnamejuniorsep] [juniors] [surnamefirstnamesep] [firstnames] (von Hoekwater jr, Taco) - -function authors.inverted(author,settings) - local firstnames, vons, surnames, juniors = author.firstnames, author.vons, author.surnames, author.juniors - local result, settings = { }, settings or defaultsettings - if vons and #vons > 0 then - result[#result+1] = concat(vons," ") - result[#result+1] = settings.vonsep or defaultsettings.vonsep - end - if surnames and #surnames > 0 then - result[#result+1] = concat(surnames," ") - if juniors and #juniors > 0 then - result[#result+1] = settings.surnamejuniorsep or defaultsettings.surnamejuniorsep - result[#result+1] = concat(juniors," ") - end - elseif juniors and #juniors > 0 then - result[#result+1] = concat(juniors," ") - end - if firstnames and #firstnames > 0 then - result[#result+1] = settings.surnamefirstnamesep or defaultsettings.surnamefirstnamesep - result[#result+1] = concat(firstnames," ") - end - return concat(result) -end - --- [vons] [vonsep] [surnames] [surnamejuniorsep] [juniors] [surnamefirstnamesep] [initials] (von Hoekwater jr, T) - -function authors.invertedshort(author,settings) - local vons, surnames, initials, juniors = author.vons, author.surnames, author.initials, author.juniors - local result, settings = { }, settings or defaultsettings - if vons and #vons > 0 then - result[#result+1] = concat(vons," ") - result[#result+1] = settings.vonsep or defaultsettings.vonsep - end - if surnames and #surnames > 0 then - result[#result+1] = concat(surnames," ") - if juniors and #juniors > 0 then - result[#result+1] = settings.surnamejuniorsep or defaultsettings.surnamejuniorsep - result[#result+1] = concat(juniors," ") - end - elseif juniors and #juniors > 0 then - result[#result+1] = concat(juniors," ") - end - if initials and #initials > 0 then - result[#result+1] = settings.surnameinitialsep or defaultsettings.surnameinitialsep - result[#result+1] = concat(the_initials(initials)," ") - end - return concat(result) -end - -local lastconcatsize = 1 - -local function concatnames(t,settings) - local namesep = settings.namesep - local lastnamesep = settings.lastnamesep - local finalnamesep = settings.finalnamesep - local lastconcatsize = #t - if lastconcatsize > 2 then - local s = { } - for i=1,lastconcatsize-2 do - s[i] = t[i] .. namesep - end - s[lastconcatsize-1], s[lastconcatsize] = t[lastconcatsize-1] .. finalnamesep, t[lastconcatsize] - return concat(s) - elseif lastconcatsize > 1 then - return concat(t,lastnamesep) - elseif lastconcatsize > 0 then - return t[1] - else - return "" - end -end - -function authors.concat(dataset,tag,field,settings) - table.setmetatableindex(settings,defaultsettings) - local combiner = settings.combiner - if not combiner or type(combiner) == "string" then - combiner = authors[combiner or "normal"] or authors.normal - end - local split = datasets[dataset].details[tag][field] - local etallimit = settings.etallimit or 1000 - local etaldisplay = settings.etaldisplay or etallimit - local max = split and #split or 0 - if max == 0 then - -- error - end - if max > etallimit and etaldisplay < max then - max = etaldisplay - end - local combined = { } - for i=1,max do - combined[i] = combiner(split[i],settings) - end - local result = concatnames(combined,settings) - if #combined <= max then - return result - else - return result .. settings.etaltext - end -end - -function commands.btxauthor(...) - context(authors.concat(...)) -end - -function authors.short(author,year) - -- todo --- local result = { } --- if author then --- local authors = splitauthors(author) --- for a=1,#authors do --- local aa = authors[a] --- local initials = aa.initials --- for i=1,#initials do --- result[#result+1] = initials[i] --- end --- local surnames = aa.surnames --- for s=1,#surnames do --- result[#result+1] = utfchar(lpegmatch(firstcharacter,surnames[s])) --- end --- end --- end --- if year then --- result[#result+1] = year --- end --- return concat(result) -end - --- We can consider creating a hashtable key -> entry but I wonder if --- pays off. - -local compare = sorters.comparers.basic -- (a,b) -local strip = sorters.strip -local splitter = sorters.splitters.utf - -function authors.preparedsort(dataset,list,sorttype_a,sorttype_b,sorttype_c) - local luadata = datasets[dataset].luadata - local details = datasets[dataset].details - local valid = { } - local splitted = { } - table.setmetatableindex(splitted,function(t,k) -- could be done in the sorter but seldom that many shared - local v = splitter(k,true) -- in other cases - t[k] = v - return v - end) - local snippets = { } - for i=1,#list do - -- either { tag, tag, ... } or { { tag, index }, { tag, index } } - local li = list[i] - local tag = type(li) == "string" and li or li[1] - local entry = luadata[tag] - local detail = details[tag] - local suffix = tostring(i) - local year = nil - local assembled = nil - if entry and detail then - local key = detail[sorttype_a] or detail[sorttype_b] or detail[sorttype_c] - if key then - -- maybe an option is to also sort the authors first - local n = #key - local s = 0 - for i=1,n do - local k = key[i] - local vons = k.vons - local surnames = k.surnames - local initials = k.initials - if vons and #vons > 0 then - s = s + 1 ; snippets[s] = concat(vons," ") - end - if surnames and #surnames > 0 then - s = s + 1 ; snippets[s] = concat(surnames," ") - end - if initials and #initials > 0 then - s = s + 1 ; snippets[s] = concat(initials," ") - end - end - assembled = concat(snippets," ",1,s) - else - assembled = "" - end - year = entry.year or "9998" - else - assembled = "" - year = "9999" - end - valid[i] = { - index = i, - split = { - splitted[strip(assembled)], - splitted[year], - splitted[suffix], - }, --- names = assembled, --- year = year, --- suffix = suffix, - } - end - return valid -end - -function authors.sorted(dataset,list,sorttype) -- experimental - local valid = authors.preparedsort(dataset,list,sorttype) - if #valid == 0 or #valid ~= #list then - return list - else - sorters.sort(valid,compare) - for i=1,#valid do - valid[i] = valid[i].index - end - return valid - end -end - --- local dataset = publications.datasets.test --- --- local function add(str) --- dataset.details[str] = { author = publications.authors.splitstring(str) } --- end --- --- add("Hagen, Hans and Hoekwater, Taco Whoever T. Ex. and Henkel Hut, Hartmut Harald von der") --- add("Hans Hagen and Taco Whoever T. Ex. Hoekwater and Hartmut Harald von der Henkel Hut") --- add("de Gennes, P. and Gennes, P. de") --- add("van't Hoff, J. H. and {van't Hoff}, J. H.") --- --- local list = table.keys(dataset.details) --- local sort = publications.authors.sorted("test",list,"author") --- local test = { } for i=1,#sort do test[i] = dataset.details[list[sort[i]]] end diff --git a/tex/context/base/publ-dat.lua b/tex/context/base/publ-dat.lua deleted file mode 100644 index 8fce94822..000000000 --- a/tex/context/base/publ-dat.lua +++ /dev/null @@ -1,529 +0,0 @@ -if not modules then modules = { } end modules ['publ-dat'] = { - version = 1.001, - comment = "this module part of publication support", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- todo: strip the @ in the lpeg instead of on do_definition and do_shortcut --- todo: store bibroot and bibrootdt - ---[[ldx-- -<p>This is a prelude to integrated bibliography support. This file just loads -bibtex files and converts them to xml so that the we access the content -in a convenient way. Actually handling the data takes place elsewhere.</p> ---ldx]]-- - -if not characters then - dofile(resolvers.findfile("char-def.lua")) - dofile(resolvers.findfile("char-ini.lua")) - dofile(resolvers.findfile("char-tex.lua")) -end - -local chardata = characters.data -local lowercase = characters.lower - -local lower, gsub, concat = string.lower, string.gsub, table.concat -local next, type = next, type -local utfchar = utf.char -local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns -local textoutf = characters and characters.tex.toutf -local settings_to_hash, settings_to_array = utilities.parsers.settings_to_hash, utilities.parsers.settings_to_array -local formatters = string.formatters -local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash -local xmlcollected, xmltext, xmlconvert = xml.collected, xml.text, xmlconvert -local setmetatableindex = table.setmetatableindex - --- todo: more allocate - -local P, R, S, V, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg - -local trace = false trackers.register("publications", function(v) trace = v end) -local report = logs.reporter("publications") - -publications = publications or { } -local publications = publications - -local datasets = publications.datasets or { } -publications.datasets = datasets - -publications.statistics = publications.statistics or { } -local publicationsstats = publications.statistics - -publicationsstats.nofbytes = 0 -publicationsstats.nofdefinitions = 0 -publicationsstats.nofshortcuts = 0 -publicationsstats.nofdatasets = 0 - -local xmlplaceholder = "<?xml version='1.0' standalone='yes'?>\n<bibtex></bibtex>" - -local defaultshortcuts = { - jan = "1", - feb = "2", - mar = "3", - apr = "4", - may = "5", - jun = "6", - jul = "7", - aug = "8", - sep = "9", - oct = "10", - nov = "11", - dec = "12", -} - -function publications.new(name) - publicationsstats.nofdatasets = publicationsstats.nofdatasets + 1 - local dataset = { - name = name or "dataset " .. publicationsstats.nofdatasets, - nofentries = 0, - shortcuts = { }, - luadata = { }, - xmldata = xmlconvert(xmlplaceholder), - -- details = { }, - nofbytes = 0, - entries = nil, -- empty == all - sources = { }, - loaded = { }, - fields = { }, - userdata = { }, - used = { }, - commands = { }, -- for statistical purposes - status = { - resources = false, - userdata = false, - }, - } - setmetatableindex(dataset,function(t,k) - -- will become a plugin - if k == "details" and publications.enhance then - dataset.details = { } - publications.enhance(dataset.name) - return dataset.details - end - end) - return dataset -end - -function publications.markasupdated(name) - if name == "string" then - datasets[name].details = nil - else - datasets.details = nil - end -end - -setmetatableindex(datasets,function(t,k) - if type(k) == "table" then - return k -- so we can use this accessor as checker - else - local v = publications.new(k) - datasets[k] = v - return v - end -end) - --- we apply some normalization - -local space = S(" \t\n\r\f") -- / " " - ------ command = P("\\") * Cc("btxcmd{") * (R("az","AZ")^1) * Cc("}") ------ command = P("\\") * (Carg(1) * C(R("az","AZ")^1) / function(list,c) list[c] = (list[c] or 0) + 1 return "btxcmd{" .. c .. "}" end) -local command = P("\\") * (Carg(1) * C(R("az","AZ")^1) * space^0 / function(list,c) list[c] = (list[c] or 0) + 1 return "btxcmd{" .. c .. "}" end) -local somemath = P("$") * ((1-P("$"))^1) * P("$") -- let's not assume nested math -local any = P(1) -local done = P(-1) -local one_l = P("{") / "" -local one_r = P("}") / "" -local two_l = P("{{") / "" -local two_r = P("}}") / "" -local special = P("#") / "\\letterhash" - -local filter_0 = S('\\{}') -local filter_1 = (1-filter_0)^0 * filter_0 -local filter_2 = Cs( --- {{...}} ... {{...}} --- two_l * (command + special + any - two_r - done)^0 * two_r * done + --- one_l * (command + special + any - one_r - done)^0 * one_r * done + - (somemath + command + special + any )^0 -) - --- Currently we expand shortcuts and for large ones (like the acknowledgements --- in tugboat.bib this is not that efficient. However, eventually strings get --- hashed again. - -local function do_shortcut(key,value,dataset) - publicationsstats.nofshortcuts = publicationsstats.nofshortcuts + 1 - dataset.shortcuts[key] = value -end - -local function getindex(dataset,luadata,tag) - local found = luadata[tag] - if found then - return found.index or 0 - else - local index = dataset.nofentries + 1 - dataset.nofentries = index - return index - end -end - -publications.getindex = getindex - --- todo: categories : metatable that lowers and also counts --- todo: fields : metatable that lowers - -local function do_definition(category,tag,tab,dataset) - publicationsstats.nofdefinitions = publicationsstats.nofdefinitions + 1 - local fields = dataset.fields - local luadata = dataset.luadata - local found = luadata[tag] - local index = getindex(dataset,luadata,tag) - local entries = { - category = lower(category), - tag = tag, - index = index, - } - for i=1,#tab,2 do - local original = tab[i] - local normalized = fields[original] - if not normalized then - normalized = lower(original) -- we assume ascii fields - fields[original] = normalized - end - local value = tab[i+1] - value = textoutf(value) - if lpegmatch(filter_1,value) then - value = lpegmatch(filter_2,value,1,dataset.commands) -- we need to start at 1 for { } - end - if normalized == "crossref" then - local parent = luadata[value] - if parent then - setmetatableindex(entries,parent) - else - -- warning - end - end - entries[normalized] = value - end - luadata[tag] = entries -end - -local function resolve(s,dataset) - return dataset.shortcuts[s] or defaultshortcuts[s] or s -- can be number -end - -local percent = P("%") -local start = P("@") -local comma = P(",") -local hash = P("#") -local escape = P("\\") -local single = P("'") -local double = P('"') -local left = P('{') -local right = P('}') -local both = left + right -local lineending = S("\n\r") -local space = S(" \t\n\r\f") -- / " " -local spacing = space^0 -local equal = P("=") ------ collapsed = (space^1)/ " " -local collapsed = (lpegpatterns.whitespace^1)/ " " - ------ balanced = lpegpatterns.balanced -local balanced = P { - [1] = ((escape * (left+right)) + (collapsed + 1 - (left+right)) + V(2))^0, - [2] = left * V(1) * right -} - -local keyword = C((R("az","AZ","09") + S("@_:-"))^1) -local key = C((1-space-equal)^1) -local tag = C((1-space-comma)^1) -local reference = keyword -local category = P("@") * C((1-space-left)^1) -local s_quoted = ((escape*single) + collapsed + (1-single))^0 -local d_quoted = ((escape*double) + collapsed + (1-double))^0 - -local b_value = (left /"") * balanced * (right /"") -local s_value = (single/"") * (b_value + s_quoted) * (single/"") -local d_value = (double/"") * (b_value + d_quoted) * (double/"") -local r_value = reference * Carg(1) /resolve - -local somevalue = s_value + d_value + b_value + r_value -local value = Cs((somevalue * ((spacing * hash * spacing)/"" * somevalue)^0)) - -local assignment = spacing * key * spacing * equal * spacing * value * spacing -local shortcut = P("@") * (P("string") + P("STRING")) * spacing * left * ((assignment * Carg(1))/do_shortcut * comma^0)^0 * spacing * right -local definition = category * spacing * left * spacing * tag * spacing * comma * Ct((assignment * comma^0)^0) * spacing * right * Carg(1) / do_definition -local comment = keyword * spacing * left * (1-right)^0 * spacing * right -local forget = percent^1 * (1-lineending)^0 - --- todo \% - -local bibtotable = (space + forget + shortcut + definition + comment + 1)^0 - --- loadbibdata -> dataset.luadata --- loadtexdata -> dataset.luadata --- loadluadata -> dataset.luadata - --- converttoxml -> dataset.xmldata from dataset.luadata - -function publications.loadbibdata(dataset,content,source,kind) - dataset = datasets[dataset] - statistics.starttiming(publications) - publicationsstats.nofbytes = publicationsstats.nofbytes + #content - dataset.nofbytes = dataset.nofbytes + #content - if source then - table.insert(dataset.sources, { filename = source, checksum = md5.HEX(content) }) - dataset.loaded[source] = kind or true - end - dataset.newtags = #dataset.luadata > 0 and { } or dataset.newtags - publications.markasupdated(dataset) - lpegmatch(bibtotable,content or "",1,dataset) - statistics.stoptiming(publications) -end - --- we could use xmlescape again - -local cleaner_0 = S('<>&') -local cleaner_1 = (1-cleaner_0)^0 * cleaner_0 -local cleaner_2 = Cs ( ( - P("<") / "<" + - P(">") / ">" + - P("&") / "&" + - P(1) -)^0) - -local compact = false -- can be a directive but then we also need to deal with newlines ... not now - -function publications.converttoxml(dataset,nice) -- we have fields ! - dataset = datasets[dataset] - local luadata = dataset and dataset.luadata - if luadata then - statistics.starttiming(publications) - statistics.starttiming(xml) - -- - local result, r = { }, 0 - -- - r = r + 1 ; result[r] = "<?xml version='1.0' standalone='yes'?>" - r = r + 1 ; result[r] = "<bibtex>" - -- - if nice then - local f_entry_start = formatters[" <entry tag='%s' category='%s' index='%s'>"] - local f_entry_stop = " </entry>" - local f_field = formatters[" <field name='%s'>%s</field>"] - for tag, entry in sortedhash(luadata) do - r = r + 1 ; result[r] = f_entry_start(tag,entry.category,entry.index) - for key, value in sortedhash(entry) do - if key ~= "tag" and key ~= "category" and key ~= "index" then - if lpegmatch(cleaner_1,value) then - value = lpegmatch(cleaner_2,value) - end - if value ~= "" then - r = r + 1 ; result[r] = f_field(key,value) - end - end - end - r = r + 1 ; result[r] = f_entry_stop - end - else - local f_entry_start = formatters["<entry tag='%s' category='%s' index='%s'>"] - local f_entry_stop = "</entry>" - local f_field = formatters["<field name='%s'>%s</field>"] - for tag, entry in next, luadata do - r = r + 1 ; result[r] = f_entry_start(entry.tag,entry.category,entry.index) - for key, value in next, entry do - if key ~= "tag" and key ~= "category" and key ~= "index" then - if lpegmatch(cleaner_1,value) then - value = lpegmatch(cleaner_2,value) - end - if value ~= "" then - r = r + 1 ; result[r] = f_field(key,value) - end - end - end - r = r + 1 ; result[r] = f_entry_stop - end - end - -- - r = r + 1 ; result[r] = "</bibtex>" - -- - result = concat(result,nice and "\n" or nil) - -- - dataset.xmldata = xmlconvert(result, { - resolve_entities = true, - resolve_predefined_entities = true, -- in case we have escaped entities - -- unify_predefined_entities = true, -- & -> & - utfize_entities = true, - } ) - -- - statistics.stoptiming(xml) - statistics.stoptiming(publications) - if lxml then - lxml.register(formatters["btx:%s"](dataset.name),dataset.xmldata) - end - end -end - -local loaders = publications.loaders or { } -publications.loaders = loaders - -function loaders.bib(dataset,filename,kind) - dataset = datasets[dataset] - local data = io.loaddata(filename) or "" - if data == "" then - report("empty file %a, nothing loaded",filename) - elseif trace then - report("loading file",filename) - end - publications.loadbibdata(dataset,data,filename,kind) -end - -function loaders.lua(dataset,filename) -- if filename is a table we load that one - dataset = datasets[dataset] - if type(dataset) == "table" then - dataset = datasets[dataset] - end - local data = type(filename) == "table" and filename or table.load(filename) - if data then - local luadata = dataset.luadata - for tag, entry in next, data do - if type(entry) == "table" then - entry.index = getindex(dataset,luadata,tag) - luadata[tag] = entry -- no cleaning yet - end - end - end -end - -function loaders.xml(dataset,filename) - dataset = datasets[dataset] - local luadata = dataset.luadata - local root = xml.load(filename) - for entry in xmlcollected(root,"/bibtex/entry") do - local attributes = entry.at - local tag = attributes.tag - local entry = { - category = attributes.category - } - for field in xmlcollected(entry,"/field") do - -- entry[field.at.name] = xmltext(field) - entry[field.at.name] = field.dt[1] -- no cleaning yet - end - -- local edt = entry.dt - -- for i=1,#edt do - -- local e = edt[i] - -- local a = e.at - -- if a and a.name then - -- t[a.name] = e.dt[1] -- no cleaning yet - -- end - -- end - entry.index = getindex(dataset,luadata,tag) - luadata[tag] = entry - end -end - -setmetatableindex(loaders,function(t,filetype) - local v = function(dataset,filename) - report("no loader for file %a with filetype %a",filename,filetype) - end - t[k] = v - return v -end) - -function publications.load(dataset,filename,kind) - dataset = datasets[dataset] - statistics.starttiming(publications) - local files = settings_to_array(filename) - for i=1,#files do - local filetype, filename = string.splitup(files[i],"::") - if not filename then - filename = filetype - filetype = file.suffix(filename) - end - local fullname = resolvers.findfile(filename,"bib") - if dataset.loaded[fullname] then -- will become better - -- skip - elseif fullname == "" then - report("no file %a",filename) - else - loaders[filetype](dataset,fullname) - end - if kind then - dataset.loaded[fullname] = kind - end - end - statistics.stoptiming(publications) - return dataset -end - -local checked = function(s,d) d[s] = (d[s] or 0) + 1 end -local checktex = ( (1-P("\\"))^1 + P("\\") * ((C(R("az","AZ")^1) * Carg(1))/checked))^0 - -function publications.analyze(dataset) - dataset = datasets[dataset] - local data = dataset.luadata - local categories = { } - local fields = { } - local commands = { } - for k, v in next, data do - categories[v.category] = (categories[v.category] or 0) + 1 - for k, v in next, v do - fields[k] = (fields[k] or 0) + 1 - lpegmatch(checktex,v,1,commands) - end - end - dataset.analysis = { - categories = categories, - fields = fields, - commands = commands, - } -end - --- str = [[ --- @COMMENT { CRAP } --- @STRING{ hans = "h a n s" } --- @STRING{ taco = "t a c o" } --- @SOMETHING{ key1, abc = "t a c o" , def = "h a n s" } --- @SOMETHING{ key2, abc = hans # taco } --- @SOMETHING{ key3, abc = "hans" # taco } --- @SOMETHING{ key4, abc = hans # "taco" } --- @SOMETHING{ key5, abc = hans # taco # "hans" # "taco"} --- @SOMETHING{ key6, abc = {oeps {oeps} oeps} } --- ]] - --- local dataset = publications.new() --- publications.tolua(dataset,str) --- publications.toxml(dataset) --- publications.toxml(dataset) --- print(dataset.xmldata) --- inspect(dataset.luadata) --- inspect(dataset.xmldata) --- inspect(dataset.shortcuts) --- print(dataset.nofbytes,statistics.elapsedtime(publications)) - --- local dataset = publications.new() --- publications.load(dataset,"IEEEabrv.bib") --- publications.load(dataset,"IEEEfull.bib") --- publications.load(dataset,"IEEEexample.bib") --- publications.toxml(dataset) --- print(dataset.nofbytes,statistics.elapsedtime(publications)) - --- local dataset = publications.new() --- publications.load(dataset,"gut.bib") --- publications.load(dataset,"komoedie.bib") --- publications.load(dataset,"texbook1.bib") --- publications.load(dataset,"texbook2.bib") --- publications.load(dataset,"texbook3.bib") --- publications.load(dataset,"texgraph.bib") --- publications.load(dataset,"texjourn.bib") --- publications.load(dataset,"texnique.bib") --- publications.load(dataset,"tugboat.bib") --- publications.toxml(dataset) --- print(dataset.nofbytes,statistics.elapsedtime(publications)) - --- print(table.serialize(dataset.luadata)) --- print(table.serialize(dataset.xmldata)) --- print(table.serialize(dataset.shortcuts)) --- print(xml.serialize(dataset.xmldata)) diff --git a/tex/context/base/publ-imp-apa.mkiv b/tex/context/base/publ-imp-apa.mkiv deleted file mode 100644 index 3f7b119af..000000000 --- a/tex/context/base/publ-imp-apa.mkiv +++ /dev/null @@ -1,547 +0,0 @@ -%D \module -%D [ file=publ-imp-apa, -%D version=2013.12.12, % based on bibl-apa.tex and later xml variant -%D title=APA bibliography style, -%D subtitle=Publications, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is therefore copyrighted -%D by \PRAGMA. See mreadme.pdf for details. - -% common - -% \loadbtxdefinitionfile[def] - -\startsetups btx:apa:common:wherefrom - \btxdoifelse {address} { - \getvariable{btx:temp}{left} - \btxdoifelse {country} { - \btxdoifelse {\getvariable{btx:temp}{label}} { - \btxflush{address}\btxcomma\btxflush{country}: \btxflush{\getvariable{btx:temp}{label}} - } { - \btxflush{address}\btxcomma\btxflush{country} - } - } { - \btxdoifelse {\getvariable{btx:temp}{label}} { - \btxflush{address}\btxcomma\btxflush{\getvariable{btx:temp}{label}} - } { - \btxflush{address} - } - } - \getvariable{btx:temp}{right} - } { - \btxdoifelse {country} { - \getvariable{btx:temp}{left} - \btxdoifelse {\getvariable{btx:temp}{label}} { - \btxflush{country}: \btxflush{\getvariable{btx:temp}{label}} - } { - \btxflush{country} - } - \getvariable{btx:temp}{right} - } { - \btxdoifelse {\getvariable{btx:temp}{label}} { - \getvariable{btx:temp}{left} - \btxflush{\getvariable{btx:temp}{label}} - \getvariable{btx:temp}{right} - } { - \getvariable{btx:temp}{otherwise} - } - } - } -\stopsetups - -% \setvariables[btx:temp][label=,left=,right=,otherwise=] - -\startsetups btx:apa:common:publisher - \begingroup - \setvariables[btx:temp][label=publisher]\relax - \btxsetup{btx:apa:common:wherefrom} - \endgroup -\stopsetups - -\startsetups btx:apa:common:organization - \begingroup - \setvariables[btx:temp][label=organization]\relax - \btxsetup{btx:apa:common:wherefrom} - \endgroup -\stopsetups - -\startsetups btx:apa:common:school - \begingroup - \setvariables[btx:temp][label=school]\relax - \btxsetup{btx:apa:common:wherefrom} - \endgroup -\stopsetups - -\startsetups btx:apa:common:institution - \begingroup - \setvariables[btx:temp][label=institution]\relax - \btxsetup{btx:apa:common:wherefrom} - \endgroup -\stopsetups - -\startsetups btx:apa:common:school:subsentence - \begingroup - \setvariables[btx:temp][label=school,left=\btxcomma,right=\btxperiod,otherwise=\btxperiod]\relax - \btxsetup{btx:apa:common:wherefrom} - \endgroup -\stopsetups - -\startsetups btx:apa:common:institution:subsentence - \begingroup - \setvariables[btx:temp][label=institution,left=\btxcomma,right=\btxperiod,otherwise=\btxperiod]\relax - \btxsetup{btx:apa:common:wherefrom} - \endgroup -\stopsetups - -\startsetups btx:apa:common:publisher:sentence - \begingroup - \setvariables[btx:temp][label=publisher,left=\btxspace,right=\btxperiod]\relax - \btxsetup{btx:apa:common:wherefrom} - \endgroup -\stopsetups - -\startsetups btx:apa:common:organization:sentence - \begingroup - \setvariables[btx:temp][label=organization,left=\btxspace,right=\btxperiod]\relax - \btxsetup{btx:apa:common:wherefrom} - \endgroup -\stopsetups - -\startsetups btx:apa:common:title-and-series - \btxdoif {title} { - \btxflush{title} - \btxdoif {series} { - \btxlparent\btxflush{series}\btxrparent - } - \btxperiod - } -\stopsetups - -\startsetups btx:apa:common:title-it-and-series - \btxdoif {title} { - \bgroup\it\btxflush{title}\/\egroup - \btxdoif {series} { - \btxlparent\btxflush{series}\btxrparent - } - \btxperiod - } -\stopsetups - -\disablemode[btx:apa:edited-book] - -\startsetups btx:apa:common:author-and-year - \btxdoif {author} { - \btxflushauthor{author} - } - \btxdoif {year} { - \btxlparent\btxflush{year}\btxrparent - } - \btxperiod -\stopsetups - -\startsetups btx:apa:common:author-or-key-and-year - \btxdoifelse {author} { - \btxflushauthor{author} - } { - \btxdoif {key} { - \btxlbracket\btxsetup{btx:format:key}\btxrbracket - } - } - \btxdoif {year} { - \btxlparent\btxflush{year}\btxrparent - } - \btxperiod -\stopsetups - -\startsetups btx:apa:common:author-editors-crossref-year - \btxdoif {author} { - \btxflushauthor{author} - } { - \btxdoifelse {editor} { - \enablemode[btx:apa:edited-book] - \btxflushauthor{editor} - \btxcomma\btxsingularplural{editor}{editor}{editors} - } { - % weird period - \btxdoif {crossref} { - \btxlbracket\btxsetup{btx:format:crossref}\btxrbracket\btxperiod - } - } - } - \btxdoif {year} { - \btxlparent\btxflush{year}\btxrparent - } - \btxperiod -\stopsetups - -\startsetups btx:apa:common:editor-or-key-and-year - \btxdoifelse {editor} { - \enablemode[btx:apa:edited-book] - \btxflushauthor{editor} - \btxcomma\btxsingularplural{editor}{editor}{editors} - } { - \btxdoif {key} { - \btxlbracket\btxsetup{btx:format:key}\btxrbracket - } - } - \btxspace - \btxdoif {year} { - \btxlparent\btxflush{year}\btxrparent - } - \btxperiod -\stopsetups - -\startsetups btx:apa:common:note - \btxdoif {note} { - \btxspace\btxflush{note}\btxperiod - } -\stopsetups - -\startsetups btx:apa:common:comment - \btxdoif {comment} { - \btxspace\btxflush{comment}\btxperiod - } -\stopsetups - -\startsetups btx:apa:common:pages:p - \btxdoif {pages} { - \btxspace\btxflush{pages}\btxspace p\btxperiod - } -\stopsetups - -\startsetups btx:apa:common:pages:pp - \btxdoif {pages} { - \btxspace\btxflush{pages}\btxspace pp\btxperiod - } -\stopsetups - -\startsetups btx:apa:common:pages:pages - \btxdoif {pages} { - \btxcomma pages~\btxflush{pages} - } -\stopsetups - -\startsetups btx:apa:common:edition:sentense - \btxdoif {edition} { - \btxspace\btxflush{edition}\btxspace edition\btxperiod - } -\stopsetups - -% check when the next is used (no period) - -% \startsetups btx:apa:common:edition -% \btxdoif {edition} { -% \btxspace\btxflush{edition}\btxspace edition -% } -% \stopsetups - -% we can share more, todo - -% specific - -\startsetups btx:apa:article - \btxsetup{btx:apa:common:author-or-key-and-year} - \btxdoif {title} { - \btxflush{title}\btxperiod - } - \btxdoifelse {journal} { - \bgroup\it\btxflush{journal}\/\egroup - } { - \btxdoif {crossref} { - In\btxspace\btxflush{crossref} - } - } - \btxdoifelse {volume} { - \btxcomma\bgroup\it\btxflush{volume}\/\egroup - \btxdoif {issue} { - \btxlparent\btxflush{issue}\btxrparent - } - \btxdoif {pages} { - \btxcomma\btxflush{pages} - } - \btxperiod - } { - \btxsetup{btx:apa:common:pages:pp} - } - \btxsetup{btx:apa:common:note} - \btxsetup{btx:apa:common:comment} -\stopsetups - -\startsetups btx:apa:book - \btxsetup{btx:apa:common:author-editors-crossref-year} - \btxdoif {title} { - \bgroup\it\btxflush{title}\/\egroup - \doifmodeelse {btx:apa:edited-book} { - \btxdoifelse {volume} { - \btxspace Number\nonbreakablespace\btxflush{volume} - \btxdoifelse {series} { - \btxspace in\nonbreakablespace\btxflush{series}\btxperiod - } { - \btxdoifelse {crossref} { - \btxspace in\btxlbracket\btxsetup{btx:format:crossref}\btxrbracket - } { - \btxperiod - } - } - } { - \btxdoif {series} { - \btxspace\btxflush{series} - } - \btxperiod - } - } { - \btxdoifelse {crossref} { - \btxdoif {chapter} { - \btxcomma\btxflush{chapter} - } - \btxsetup{btx:apa:common:pages:pages} - \btxperiod - \btxdoif {volume} { - Volume\nonbreakablespace\btxflush{volume}\btxspace of\nonbreakablespace - } - } { - \btxdoif {volume} { - \btxcomma volume\nonbreakablespace\btxflush{volume} - \btxdoif {series} { - \btxspace of\nonbreakablespace\bgroup\it\btxflush{series}\/\egroup - } - \btxdoif {chapter} { - \btxcomma\btxflush{chapter} - } - \btxsetup{btx:apa:common:pages:pages} - } - \btxperiod - } - } - } - \btxsetup{btx:apa:common:edition:sentence} - \btxsetup{btx:apa:common:publisher:sentence} - \btxsetup{btx:apa:common:pages:p}% twice? - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:inbook - \btxsetup{btx:apa:common:author-editors-crossref-year} - \btxdoifelse {title} { - \bgroup\it\btxflush{title}\/\egroup - } { - \doifmodeelse {btx:apa:edited-book} { - \btxdoifelse {volume} { - \btxspace number\nonbreakablespace\btxflush{volume} - \btxdoifelse {series} { - \btxspace in\nonbreakablespace\btxflush{series}\btxperiod - } { - \btxdoifelse {crossref} { - \btxspace in\btxlbracket\btxsetup{btx:format:crossref}\btxrbracket - } { - \btxperiod - } - } - } { - \btxdoif {series} { - \btxspace\btxflush{series}\btxperiod - } - } - } { - \btxdoifelse {crossref} { - \btxdoif {chapter} { - \btxcomma\btxflush{chapter} - } - \btxsetup{btx:apa:common:pages:pages} - \btxdoif {volume} { - Volume\nonbreakablespace\btxflush{volume}\btxspace of\nonbreakablespace - } - \btxdoif {crossref} { - \btxlbracket\btxsetup{btx:format:crossref}\btxrbracket - } - } { - \btxdoif {volume} { - \btxcomma volume\nonbreakablespace\btxflush{volume} - \btxdoif {series} { - \btxspace of\nonbreakablespace\bgroup\it\btxflush{series}\/\egroup - } - \btxdoif {chapter} { - \btxcomma\btxflush{chapter} - } - \btxsetup{btx:apa:common:pages:pages} - \btxperiod - } - } - } - } - \btxspace - \btxsetup{btx:apa:common:edition:sentence} - \btxsetup{btx:apa:common:publisher} - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:booklet - \btxsetup{btx:apa:common:author-or-key-and-year} - \btxsetup{btx:apa:common:title-it-and-series} - \btxsetup{btx:apa:common:edition:sentence} - \btxsetup{btx:apa:common:publication:sentence} - \btxsetup{btx:apa:common:pages:p} - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:manual - \btxsetup{btx:apa:common:author-or-key-and-year} - \btxsetup{btx:apa:common:title-it-and-series} - \btxsetup{btx:apa:common:edition:sentence} - \btxsetup{btx:apa:common:organization:sentence} - \btxsetup{btx:apa:common:pages:p} - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:incollection - \btxsetup{btx:apa:common:author-and-year} - \btxdoif {arttitle} { - \btxflush{arttitle}\btxperiod - } - In\btxspace - \btxdoifelse {title} { - \btxflushauthor{editor}\btxcomma - \bgroup\it\btxflush{title}\/\egroup - \btxdoif {series} { - \btxdoif {volume} { - \btxcomma number\btxspace\btxflush{volume}\btxspace in - } - \btxspace\btxflush{series} - } - \btxdoif {chapter} { - \btxcomma\btxflush{chapter}\btxspace - } - \btxsetup{btx:apa:common:pages:pages} - \btxdoif {edition} { - \btxspace\btxflush{edition}\btxspace edition - } - \btxsetup{btx:apa:common:publisher:sentence} - } { - \btxdoif {crossref} { - \btxlbracket\btxsetup{btx:format:crossref}\btxrbracket - } - \btxdoif {chapter} { - \btxcomma\btxflush{chapter} - } - \btxspace - \btxsetup{btx:apa:common:pages:pages} - } - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:inproceedings - \btxsetup{btx:apa:common:author-and-year} - \btxdoif {arttitle} { - \btxflush{arttitle}\btxperiod - } - In\btxspace - \btxdoifelse {title} { - \btxdoif {editor} { - \btxflush{btx:apa:format:editors} - \btxcomma\btxsingularplural{editor}{editor}{editors}\btxcomma - } - \bgroup\it\btxflush{title}\/\egroup - \btxdoif {series} { - \btxdoif {volume} { - \btxcomma number~\btxflush{volume} in - } - \btxspace - \btxflush{series} - } - \btxdoif {chapter} { - \btxcomma\btxflush{chapter}\btxspace - } - \btxsetup{btx:apa:common:pages:pages} - \btxperiod - \btxsetup{btx:apa:common:organization:sentence} - } { - \btxdoif {crossref} { - \btxlbracket\btxsetup{btx:format:crossref}\btxrbracket - } - \btxdoif {chapter} { - \btxcomma\btxflush{chapter}\btxspace - } - \btxsetup{btx:apa:common:pages:pages} - \btxperiod - } - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:proceedings - \btxsetup{btx:apa:common:editor-or-key-and-year} - \btxdoif {title} { - \bgroup\it\btxflush{title}\/\egroup - \btxdoif {volume} { - \btxcomma number\btxspace\btxflush{volume}\btxspace in\btxspace - } - \btxdoif {chapter} { - \btxcomma\btxflush{chapter}\btxspace - } - \btxsetup{btx:apa:common:pages:pages} - \btxperiod - \btxsetup{btx:apa:common:organization:sentence} - } - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:common:thesis - \btxsetup{btx:apa:common:author-and-year} - \btxsetup{btx:apa:common:title-it-and-series} - \btxdoifelse {type} { - \btxflush{type} - } { - \getvariable{btx:temp}{label} - } - \btxsetup{btx:apa:common:school:subsentence} - \btxsetup{btx:apa:common:pages:p} - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:mastersthesis - \setvariables[btx:temp][label=Master's thesis] - \btxsetup{btx:apa:common:thesis} -\stopsetups - -\startsetups btx:apa:phdthesis - \setvariables[btx:temp][label=PhD thesis] - \btxsetup{btx:apa:common:thesis} -\stopsetups - -\startsetups btx:apa:techreport - \btxsetup{btx:apa:common:author-and-year} - \btxsetup{btx:apa:common:title-and-series} - \btxdoifelse {type} { - \btxflush{type} - \btxdoif {volume} { - \btxspace\btxflush{volume} - } - } { - \btxspace Technical Report - } - \btxsetup{btx:apa:common:institution:subsentence} - \btxsetup{btx:apa:common:pages:p} - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:misc - \btxsetup{btx:apa:common:author-and-year} - \btxsetup{btx:apa:common:title-and-series} - \btxsetup{btx:apa:common:publisher:sentence} - \btxsetup{btx:apa:common:pages:p} - \btxsetup{btx:apa:common:note} -\stopsetups - -\startsetups btx:apa:unpublished - \btxsetup{btx:apa:common:author-and-year} - \btxsetup{btx:apa:common:title-and-series} - \btxsetup{btx:apa:common:pages:p} - \btxdoif {type} { - \btxlparent\btxflush{type}\btxrparent - } - \btxsetup{btx:apa:common:note} -\stopsetups - -\endinput diff --git a/tex/context/base/publ-imp-cite.mkiv b/tex/context/base/publ-imp-cite.mkiv deleted file mode 100644 index d64c2132c..000000000 --- a/tex/context/base/publ-imp-cite.mkiv +++ /dev/null @@ -1,74 +0,0 @@ -%D \module -%D [ file=publ-imp-cite, -%D version=2013.12.24, -%D title=\CONTEXT\ Publication Support, -%D subtitle=XML, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\startsetups btx:cite:author - \btxcitevariant{author} -\stopsetups - -\startsetups btx:cite:authoryear - \btxcitevariant{authoryear} -\stopsetups - -\startsetups btx:cite:authoryears - \btxcitevariant{authoryears} -\stopsetups - -% \startsetups btx:cite:authornum -% \btxcitevariant{author} -% \btxcitevariantparameter\c!inbetween -% \btxcitevariant{num} -% \stopsetups - -\startsetups btx:cite:authornum - \btxcitevariant{authornum} -\stopsetups - -\startsetups btx:cite:year - \btxcitevariant{year} -\stopsetups - -\startsetups btx:cite:short - \btxcitevariant{short} -\stopsetups - -\startsetups btx:cite:serial - \btxcitevariant{serial} -\stopsetups - -\startsetups btx:cite:key - \currentbtxtag % \btxcitevariant{tag} -\stopsetups - -\startsetups btx:cite:doi - todo: \btxcitevariant{doi} -\stopsetups - -\startsetups btx:cite:url - todo: \btxcitevariant{url} -\stopsetups - -\startsetups btx:cite:type - \btxcitevariant{category} -\stopsetups - -\startsetups btx:cite:page - \btxcitevariant{page} -\stopsetups - -\startsetups btx:cite:none - % dummy -\stopsetups - -\startsetups btx:cite:num - \btxcitevariant{num} -\stopsetups diff --git a/tex/context/base/publ-imp-commands.mkiv b/tex/context/base/publ-imp-commands.mkiv deleted file mode 100644 index 14e2dbae1..000000000 --- a/tex/context/base/publ-imp-commands.mkiv +++ /dev/null @@ -1,15 +0,0 @@ -\unprotect - -% for tugboat - -\definebtxcommand\hbox {\hbox} -\definebtxcommand\vbox {\vbox} -\definebtxcommand\llap {\llap} -\definebtxcommand\rlap {\rlap} -\definebtxcommand\url #1{\hyphenatedurl{#1}} -\definebtxcommand\acro #1{\dontleavehmode{\smallcaps#1}} - -\let\<< -\let\<> - -\protect \endinput diff --git a/tex/context/base/publ-imp-definitions.mkiv b/tex/context/base/publ-imp-definitions.mkiv deleted file mode 100644 index 2cf2e3e8e..000000000 --- a/tex/context/base/publ-imp-definitions.mkiv +++ /dev/null @@ -1,68 +0,0 @@ -%D \module -%D [ file=publ-imp-def, -%D version=2013.12.24, -%D title=\CONTEXT\ Publication Support, -%D subtitle=Definitions, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -%D Here we collect some helper setups. We assume that checking of a field -%D happens in the calling setup, if only because that is the place where -%D fences are also dealt with. - -\unprotect - -\startxmlsetups btx:format:crossref - \cite[\btxfield{crossref}] -\stopxmlsetups - -\startxmlsetups btx:format:key - \btxfield{short} -\stopxmlsetups - -\startxmlsetups btx:format:doi - \edef\currentbtxfielddoi{\btxfield{doi}} - \ifx\currentbtxfielddoi\empty - {\tttf no-doi} - \else\ifconditional\btxinteractive - \goto{\hyphenatedurl{\currentbtxfielddoi}}[url(http://dx.doi.org/\currentbtxfielddoi)] - \else - \hyphenatedurl{\currentbtxfielddoi} - \fi\fi -\stopxmlsetups - -\startxmlsetups btx:format:url - \edef\currentbtxfieldurl{\btxfield{url}} - \ifx\currentbtxfieldurl\empty - {\tttf no-url} - \else\ifconditional\btxinteractive - \goto{\hyphenatedurl{\currentbtxfieldurl}}[url(\currentbtxfieldurl)] - \else - \hyphenatedurl{\currentbtxfieldurl} - \fi\fi -\stopxmlsetups - -\startxmlsetups btx:format:month - \edef\currentbtxfieldmonth{\btxfield{month}} - \ifx\currentbtxfieldmonth\empty - {\tttf no-month} - \else - \edef\p_monthconversion{\btxlistvariantparameter\c!monthconversion} - \ifx\p_monthconversion\empty % month month:mnem - \currentbtxfieldmonth - \else - \doifnumberelse \currentbtxfieldmonth { - \convertnumber\p_monthconversion\currentbtxfieldmonth - } { - \currentbtxfieldmonth - } - \fi - \fi -\stopxmlsetups - -\protect diff --git a/tex/context/base/publ-ini.lua b/tex/context/base/publ-ini.lua deleted file mode 100644 index 6bf6714da..000000000 --- a/tex/context/base/publ-ini.lua +++ /dev/null @@ -1,1425 +0,0 @@ -if not modules then modules = { } end modules ['publ-ini'] = { - version = 1.001, - comment = "this module part of publication support", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- for the moment here - -local lpegmatch = lpeg.match -local P, C, Ct, Cs = lpeg.P, lpeg.C, lpeg.Ct, lpeg.Cs - -local lpegmatch = lpeg.match -local pattern = Cs((1 - P(1) * P(-1))^0 * (P(".")/"" + P(1))) - -local manipulators = { - stripperiod = function(str) return lpegmatch(pattern,str) end, - uppercase = characters.upper, - lowercase = characters.lower, -} - -local manipulation = C((1-P("->"))^1) * P("->") * C(P(1)^0) - -local pattern = manipulation / function(operation,str) - local manipulator = manipulators[operation] - return manipulator and manipulator(str) or str -end - -local function manipulated(str) - return lpegmatch(pattern,str) or str -end - -utilities.parsers.manipulation = manipulation -utilities.parsers.manipulators = manipulators -utilities.parsers.manipulated = manipulated - -function commands.manipulated(str) - context(manipulated(str)) -end - --- use: for rest in gmatch(reference,"[^, ]+") do - -local next, rawget, type = next, rawget, type -local match, gmatch, format, gsub = string.match, string.gmatch, string.format, string.gsub -local concat, sort = table.concat, table.sort -local utfsub = utf.sub -local formatters = string.formatters -local allocate = utilities.storage.allocate -local settings_to_array, settings_to_set = utilities.parsers.settings_to_array, utilities.parsers.settings_to_set -local sortedkeys, sortedhash = table.sortedkeys, table.sortedhash -local lpegmatch = lpeg.match -local P, C, Ct = lpeg.P, lpeg.C, lpeg.Ct - -local report = logs.reporter("publications") -local trace = false trackers.register("publications", function(v) trace = v end) - -local datasets = publications.datasets - -local variables = interfaces.variables - -local v_local = variables["local"] -local v_global = variables["global"] - -local v_force = variables.force -local v_standard = variables.standard -local v_start = variables.start -local v_none = variables.none -local v_left = variables.left -local v_right = variables.right -local v_middle = variables.middle -local v_inbetween = variables.inbetween - -local v_short = variables.short -local v_cite = variables.cite -local v_default = variables.default -local v_reference = variables.reference -local v_dataset = variables.dataset -local v_author = variables.author or "author" -local v_editor = variables.editor or "editor" - -local numbertochar = converters.characters - -local logsnewline = logs.newline -local logspushtarget = logs.pushtarget -local logspoptarget = logs.poptarget -local csname_id = token.csname_id - -local basicsorter = sorters.basicsorter -- (a,b) -local sortcomparer = sorters.comparers.basic -- (a,b) -local sortstripper = sorters.strip -local sortsplitter = sorters.splitters.utf - -local context = context - -local ctx_btxlistparameter = context.btxlistparameter -local ctx_btxcitevariantparameter = context.btxcitevariantparameter -local ctx_btxlistvariantparameter = context.btxlistvariantparameter -local ctx_btxdomarkcitation = context.btxdomarkcitation -local ctx_setvalue = context.setvalue -local ctx_firstoftwoarguments = context.firstoftwoarguments -local ctx_secondoftwoarguments = context.secondoftwoarguments -local ctx_firstofoneargument = context.firstofoneargument -local ctx_gobbleoneargument = context.gobbleoneargument -local ctx_btxdirectlink = context.btxdirectlink -local ctx_btxhandlelistentry = context.btxhandlelistentry -local ctx_btxchecklistentry = context.btxchecklistentry -local ctx_dodirectfullreference = context.dodirectfullreference -local ctx_directsetup = context.directsetup - -statistics.register("publications load time", function() - local publicationsstats = publications.statistics - local nofbytes = publicationsstats.nofbytes - if nofbytes > 0 then - return string.format("%s seconds, %s bytes, %s definitions, %s shortcuts", - statistics.elapsedtime(publications),nofbytes,publicationsstats.nofdefinitions,publicationsstats.nofshortcuts) - else - return nil - end -end) - -luatex.registerstopactions(function() - logspushtarget("logfile") - logsnewline() - report("start used btx commands") - logsnewline() - local undefined = csname_id("undefined*crap") - for name, dataset in sortedhash(datasets) do - for command, n in sortedhash(dataset.commands) do - local c = csname_id(command) - if c and c ~= undefined then - report("%-20s %-20s % 5i %s",name,command,n,"known") - else - local u = csname_id(utf.upper(command)) - if u and u ~= undefined then - report("%-20s %-20s % 5i %s",name,command,n,"KNOWN") - else - report("%-20s %-20s % 5i %s",name,command,n,"unknown") - end - end - end - end - logsnewline() - report("stop used btxcommands") - logsnewline() - logspoptarget() -end) - --- multipass, we need to sort because hashing is random per run and not per --- version (not the best changed feature of lua) - -local collected = allocate() -local tobesaved = allocate() - --- we use a a dedicated (and efficient as it know what it deals with) serializer, --- also because we need to ignore the 'details' field - -local function serialize(t) - local f_key_table = formatters[" [%q] = {"] - local f_key_string = formatters[" %s = %q,"] - local r = { "return {" } - local m = 1 - for tag, entry in sortedhash(t) do - m = m + 1 - r[m] = f_key_table(tag) - local s = sortedkeys(entry) - for i=1,#s do - local k = s[i] - -- if k ~= "details" then - m = m + 1 - r[m] = f_key_string(k,entry[k]) - -- end - end - m = m + 1 - r[m] = " }," - end - r[m] = "}" - return concat(r,"\n") -end - -local function finalizer() - local prefix = tex.jobname -- or environment.jobname - local setnames = sortedkeys(datasets) - for i=1,#setnames do - local name = setnames[i] - local dataset = datasets[name] - local userdata = dataset.userdata - local checksum = nil - local username = file.addsuffix(file.robustname(formatters["%s-btx-%s"](prefix,name)),"lua") - if userdata and next(userdata) then - if job.passes.first then - local newdata = serialize(userdata) - checksum = md5.HEX(newdata) - io.savedata(username,newdata) - end - else - os.remove(username) - username = nil - end - local loaded = dataset.loaded - local sources = dataset.sources - local used = { } - for i=1,#sources do - local source = sources[i] - if loaded[source.filename] ~= "previous" then -- or loaded[source.filename] == "current" - used[#used+1] = source - end - end - tobesaved[name] = { - usersource = { - filename = username, - checksum = checksum, - }, - datasources = used, - } - end -end - -local function initializer() - statistics.starttiming(publications) -collected = publications.collected or collected -- for the moment as we load runtime - for name, state in next, collected do - local dataset = datasets[name] - local datasources = state.datasources - local usersource = state.usersource - if datasources then - for i=1,#datasources do - local filename = datasources[i].filename - publications.load(dataset,filename,"previous") - end - end - if usersource then - dataset.userdata = table.load(usersource.filename) or { } - end - end - statistics.stoptiming(publications) - function initializer() end -- will go, for now, runtime loaded -end - -job.register('publications.collected',tobesaved,initializer,finalizer) - -if not publications.authors then - initializer() -- for now, runtime loaded -end - --- basic access - -local function getfield(dataset,tag,name) - local d = datasets[dataset].luadata[tag] - return d and d[name] -end - -local function getdetail(dataset,tag,name) - local d = datasets[dataset].details[tag] - return d and d[name] -end - -function commands.btxsingularorplural(dataset,tag,name) -- todo: make field dependent - local d = datasets[dataset].details[tag] - if d then - d = d[name] - end - if d then - d = #d <= 1 - end - commands.doifelse(d) -end - --- basic loading - -function commands.usebtxdataset(name,filename) - publications.load(datasets[name],filename,"current") -end - -function commands.convertbtxdatasettoxml(name,nice) - publications.converttoxml(datasets[name],nice) -end - --- enhancing - -local splitauthorstring = publications.authors.splitstring - -local pagessplitter = lpeg.splitat(P("-")^1) - --- maybe not redo when already done - -function publications.enhance(dataset) -- for the moment split runs (maybe publications.enhancers) - statistics.starttiming(publications) - if type(dataset) == "string" then - dataset = datasets[dataset] - end - local luadata = dataset.luadata - local details = dataset.details - -- author, editor - for tag, entry in next, luadata do - local author = entry.author - local editor = entry.editor - details[tag] = { - author = author and splitauthorstring(author), - editor = editor and splitauthorstring(editor), - } - end - -- short - local shorts = { } - for tag, entry in next, luadata do - local author = details[tag].author - if author then - -- number depends on sort order - local t = { } - if #author == 0 then - -- what - else - local n = #author == 1 and 3 or 1 - for i=1,#author do - local surnames = author[i].surnames - if not surnames or #surnames == 0 then - -- error - else - t[#t+1] = utfsub(surnames[1],1,n) - end - end - end - local year = tonumber(entry.year) or 0 - local short = formatters["%t%02i"](t,math.mod(year,100)) - local s = shorts[short] - if not s then - shorts[short] = tag - elseif type(s) == "string" then - shorts[short] = { s, tag } - else - s[#s+1] = tag - end - else - -- - end - end - for short, tags in next, shorts do - if type(tags) == "table" then - sort(tags) - for i=1,#tags do --- details[tags[i]].short = short .. numbertochar(i) -local detail = details[tags[i]] -detail.short = short -detail.suffix = numbertochar(i) - end - else - details[tags].short = short - end - end - -- pages - for tag, entry in next, luadata do - local pages = entry.pages - if pages then - local first, last = lpegmatch(pagessplitter,pages) - details[tag].pages = first and last and { first, last } or pages - end - end - -- keywords - for tag, entry in next, luadata do - local keyword = entry.keyword - if keyword then - details[tag].keyword = settings_to_set(keyword) - end - end - statistics.stoptiming(publications) -end - -function commands.addbtxentry(name,settings,content) - local dataset = datasets[name] - if dataset then - publications.addtexentry(dataset,settings,content) - end -end - -function commands.setbtxdataset(name) - local dataset = rawget(datasets,name) - if dataset then - context(name) - else - report("unknown dataset %a",name) - end -end - -function commands.setbtxentry(name,tag) - local dataset = rawget(datasets,name) - if dataset then - if dataset.luadata[tag] then - context(tag) - else - report("unknown tag %a in dataset %a",tag,name) - end - else - report("unknown dataset %a",name) - end -end - --- rendering of fields (maybe multiple manipulators) - -local manipulation = utilities.parsers.manipulation -local manipulators = utilities.parsers.manipulators - --- local function checked(field) --- local m, f = lpegmatch(manipulation,field) --- if m then --- return manipulators[m], f or field --- else --- return nil, field --- end --- end - -local manipulation = Ct((C((1-P("->"))^1) * P("->"))^1) * C(P(1)^0) - -local function checked(field) - local m, f = lpegmatch(manipulation,field) - if m then - return m, f or field - else - return nil, field - end -end - -local function manipulated(actions,str) - for i=1,#actions do - local action = manipulators[actions[i]] - if action then - str = action(str) or str - end - end - return str -end - -function commands.btxflush(name,tag,field) - local dataset = rawget(datasets,name) - if dataset then - local fields = dataset.luadata[tag] - if fields then - local manipulator, field = checked(field) - local value = fields[field] - if type(value) == "string" then - -- context(manipulator and manipulator(value) or value) - context(manipulator and manipulated(manipulator,value) or value) - return - end - local details = dataset.details[tag] - if details then - local value = details[field] - if type(value) == "string" then - -- context(manipulator and manipulator(value) or value) - context(manipulator and manipulated(manipulator,value) or value) - return - end - end - report("unknown field %a of tag %a in dataset %a",field,tag,name) - else - report("unknown tag %a in dataset %a",tag,name) - end - else - report("unknown dataset %a",name) - end -end - -function commands.btxdetail(name,tag,field) - local dataset = rawget(datasets,name) - if dataset then - local details = dataset.details[tag] - if details then - local manipulator, field = checked(field) - local value = details[field] - if type(value) == "string" then - -- context(manipulator and manipulator(value) or value) - context(manipulator and manipulated(manipulator,value) or value) - else - report("unknown detail %a of tag %a in dataset %a",field,tag,name) - end - else - report("unknown tag %a in dataset %a",tag,name) - end - else - report("unknown dataset %a",name) - end -end - -function commands.btxfield(name,tag,field) - local dataset = rawget(datasets,name) - if dataset then - local fields = dataset.luadata[tag] - if fields then - local manipulator, field = checked(field) - local value = fields[field] - if type(value) == "string" then - -- context(manipulator and manipulator(value) or value) - context(manipulator and manipulated(manipulator,value) or value) - else - report("unknown field %a of tag %a in dataset %a",field,tag,name) - end - else - report("unknown tag %a in dataset %a",tag,name) - end - else - report("unknown dataset %a",name) - end -end - --- testing: to be speed up with testcase - -function commands.btxdoifelse(name,tag,field) - local dataset = rawget(datasets,name) - if dataset then - local data = dataset.luadata[tag] - local value = data and data[field] - if value and value ~= "" then - ctx_firstoftwoarguments() - return - end - end - ctx_secondoftwoarguments() -end - -function commands.btxdoif(name,tag,field) - local dataset = rawget(datasets,name) - if dataset then - local data = dataset.luadata[tag] - local value = data and data[field] - if value and value ~= "" then - ctx_firstofoneargument() - return - end - end - ctx_gobbleoneargument() -end - -function commands.btxdoifnot(name,tag,field) - local dataset = rawget(datasets,name) - if dataset then - local data = dataset.luadata[tag] - local value = data and data[field] - if value and value ~= "" then - ctx_gobbleoneargument() - return - end - end - ctx_firstofoneargument() -end - --- -- alternative approach: keep data at the tex end - -function publications.listconcat(t) - local n = #t - if n > 0 then - context(t[1]) - if n > 1 then - if n > 2 then - for i=2,n-1 do - ctx_btxlistparameter("sep") - context(t[i]) - end - ctx_btxlistparameter("finalsep") - else - ctx_btxlistparameter("lastsep") - end - context(t[n]) - end - end -end - -function publications.citeconcat(t) - local n = #t - if n > 0 then - context(t[1]) - if n > 1 then - if n > 2 then - for i=2,n-1 do - ctx_btxcitevariantparameter("sep") - context(t[i]) - end - ctx_btxcitevariantparameter("finalsep") - else - ctx_btxcitevariantparameter("lastsep") - end - context(t[n]) - end - end -end - -function publications.singularorplural(singular,plural) - if lastconcatsize and lastconcatsize > 1 then - context(plural) - else - context(singular) - end -end - --- function commands.makebibauthorlist(settings) -- ? --- if not settings then --- return --- end --- local dataset = datasets[settings.dataset] --- if not dataset or dataset == "" then --- return --- end --- local tag = settings.tag --- if not tag or tag == "" then --- return --- end --- local asked = settings_to_array(tag) --- if #asked == 0 then --- return --- end --- local compress = settings.compress --- local interaction = settings.interactionn == v_start --- local limit = tonumber(settings.limit) --- local found = { } --- local hash = { } --- local total = 0 --- local luadata = dataset.luadata --- for i=1,#asked do --- local tag = asked[i] --- local data = luadata[tag] --- if data then --- local author = data.a or "Xxxxxxxxxx" --- local year = data.y or "0000" --- if not compress or not hash[author] then --- local t = { --- author = author, --- name = name, -- first --- year = { [year] = name }, --- } --- total = total + 1 --- found[total] = t --- hash[author] = t --- else --- hash[author].year[year] = name --- end --- end --- end --- for i=1,total do --- local data = found[i] --- local author = data.author --- local year = table.keys(data.year) --- table.sort(year) --- if interaction then --- for i=1,#year do --- year[i] = formatters["\\bibmaybeinteractive{%s}{%s}"](data.year[year[i]],year[i]) --- end --- end --- ctx_setvalue("currentbibyear",concat(year,",")) --- if author == "" then --- ctx_setvalue("currentbibauthor","") --- else -- needs checking --- local authors = settings_to_array(author) -- {{}{}},{{}{}} --- local nofauthors = #authors --- if nofauthors == 1 then --- if interaction then --- author = formatters["\\bibmaybeinteractive{%s}{%s}"](data.name,author) --- end --- ctx_setvalue("currentbibauthor",author) --- else --- limit = limit or nofauthors --- if interaction then --- for i=1,#authors do --- authors[i] = formatters["\\bibmaybeinteractive{%s}{%s}"](data.name,authors[i]) --- end --- end --- if limit == 1 then --- ctx_setvalue("currentbibauthor",authors[1] .. "\\bibalternative{otherstext}") --- elseif limit == 2 and nofauthors == 2 then --- ctx_setvalue("currentbibauthor",concat(authors,"\\bibalternative{andtext}")) --- else --- for i=1,limit-1 do --- authors[i] = authors[i] .. "\\bibalternative{namesep}" --- end --- if limit < nofauthors then --- authors[limit+1] = "\\bibalternative{otherstext}" --- ctx_setvalue("currentbibauthor",concat(authors,"",1,limit+1)) --- else --- authors[limit-1] = authors[limit-1] .. "\\bibalternative{andtext}" --- ctx_setvalue("currentbibauthor",concat(authors)) --- end --- end --- end --- end --- -- the following use: currentbibauthor and currentbibyear --- if i == 1 then --- context.ixfirstcommand() --- elseif i == total then --- context.ixlastcommand() --- else --- context.ixsecondcommand() --- end --- end --- end - -local patterns = { "publ-imp-%s.mkiv", "publ-imp-%s.tex" } - -local function failure(name) - report("unknown library %a",name) -end - -local function action(name,foundname) - context.input(foundname) -end - -function commands.loadbtxdefinitionfile(name) -- a more specific name - commands.uselibrary { - name = gsub(name,"^publ%-",""), - patterns = patterns, - action = action, - failure = failure, - onlyonce = false, - } -end - --- lists: - -publications.lists = publications.lists or { } -local lists = publications.lists - -local context = context -local structures = structures - -local references = structures.references -local sections = structures.sections - --- per rendering - -local renderings = { } --- per dataset - -table.setmetatableindex(renderings,function(t,k) - local v = { - list = { }, - done = { }, - alldone = { }, - used = { }, - registered = { }, - ordered = { }, - shorts = { }, - method = v_none, - currentindex = 0, - } - t[k] = v - return v -end) - --- why shorts vs tags: only for sorting - -function lists.register(dataset,tag,short) -- needs checking now that we split - local r = renderings[dataset] - if not short or short == "" then - short = tag - end - if trace then - report("registering publication entry %a with shortcut %a",tag,short) - end - local top = #r.registered + 1 - -- do we really need these - r.registered[top] = tag - r.ordered [tag] = top - r.shorts [tag] = short -end - -function lists.nofregistered(dataset) - return #renderings[dataset].registered -end - -function lists.setmethod(dataset,method) - local r = renderings[dataset] - r.method = method or v_none - r.list = { } - r.done = { } -end - -local function validkeyword(dataset,tag,keyword) - local ds = datasets[dataset] - if not ds then - report("unknown dataset %a",dataset) - return - end - local dt = ds.details[tag] - if not dt then - report("no details for tag %a",tag) - return - end - local kw = dt.keyword - if kw then --- inspect(keyword) --- inspect(kw) - for k in next, keyword do - if kw[k] then - return true - end - end - end -end - -function lists.collectentries(specification) - local dataset = specification.btxdataset - if not dataset then - return - end - local rendering = renderings[dataset] --- specification.names = "btx" - local method = rendering.method - if method == v_none then - return - end --- method=v_local -------------------- - local result = structures.lists.filter(specification) - -- - local keyword = specification.keyword - if keyword and keyword ~= "" then - keyword = settings_to_set(keyword) - else - keyword = nil - end - lists.result = result - local section = sections.currentid() - local list = rendering.list - local done = rendering.done - local alldone = rendering.alldone - if method == v_local then - for listindex=1,#result do - local r = result[listindex] - local u = r.userdata - if u and u.btxset == dataset then - local tag = u.btxref - if tag and done[tag] ~= section then - if not keyword or validkeyword(dataset,tag,keyword) then - done[tag] = section - alldone[tag] = true - list[#list+1] = { tag, listindex } - end - end - end - end - elseif method == v_global then - for listindex=1,#result do - local r = result[listindex] - local u = r.userdata - if u and u.btxset == dataset then - local tag = u.btxref - if tag and not alldone[tag] and done[tag] ~= section then - if not keyword or validkeyword(dataset,tag,keyword) then - done[tag] = section - alldone[tag] = true - list[#list+1] = { tag, listindex } - end - end - end - end - elseif method == v_force then - -- only for checking, can have duplicates, todo: collapse page numbers, although - -- we then also needs deferred writes - for listindex=1,#result do - local r = result[listindex] - local u = r.userdata - if u and u.btxset == dataset then - local tag = u.btxref - if tag then - if not keyword or validkeyword(dataset,tag,keyword) then - list[#list+1] = { tag, listindex } - end - end - end - end - elseif method == v_dataset then - local luadata = datasets[dataset].luadata - for tag, data in table.sortedhash(luadata) do - if not keyword or validkeyword(dataset,tag,keyword) then - list[#list+1] = { tag } - end - end - end -end - -lists.sorters = { - [v_short] = function(dataset,rendering,list) - local shorts = rendering.shorts - local function compare(a,b) - local aa, bb = a and a[1], b and b[1] - if aa and bb then - aa, bb = shorts[aa], shorts[bb] - return aa and bb and aa < bb - end - return false - end - sort(list,compare) - end, - [v_reference] = function(dataset,rendering,list) - local function compare(a,b) - local aa, bb = a and a[1], b and b[1] - if aa and bb then - return aa and bb and aa < bb - end - return false - end - sort(list,compare) - end, - [v_dataset] = function(dataset,rendering,list) - local function compare(a,b) - local aa, bb = a and a[1], b and b[1] - if aa and bb then - aa, bb = list[aa].index or 0, list[bb].index or 0 - return aa and bb and aa < bb - end - return false - end - sort(list,compare) - end, - -- [v_default] = function(dataset,rendering,list) -- not really needed - -- local ordered = rendering.ordered - -- local function compare(a,b) - -- local aa, bb = a and a[1], b and b[1] - -- if aa and bb then - -- aa, bb = ordered[aa], ordered[bb] - -- return aa and bb and aa < bb - -- end - -- return false - -- end - -- sort(list,compare) - -- end, - [v_author] = function(dataset,rendering,list) - local valid = publications.authors.preparedsort(dataset,list,v_author,v_editor) - if #valid == 0 or #valid ~= #list then - -- nothing to sort - else - -- if needed we can wrap compare and use the list directly but this is cleaner - sorters.sort(valid,sortcomparer) - for i=1,#valid do - local v = valid[i] - valid[i] = list[v.index] - end - return valid - end - end, -} - -function lists.flushentries(dataset,sortvariant) - local rendering = renderings[dataset] - local list = rendering.list - local sort = lists.sorters[sortvariant] or lists.sorters[v_default] - if type(sort) == "function" then - list = sort(dataset,rendering,list) or list - end - for i=1,#list do - ctx_setvalue("currentbtxindex",i) - ctx_btxhandlelistentry(list[i][1]) -- we can pass i here too ... more efficient to avoid the setvalue - end -end - -function lists.fetchentries(dataset) - local list = renderings[dataset].list - for i=1,#list do - ctx_setvalue("currentbtxindex",i) - ctx_btxchecklistentry(list[i][1]) - end -end - -function lists.filterall(dataset) - local r = renderings[dataset] - local list = r.list - local registered = r.registered - for i=1,#registered do - list[i] = { registered[i], i } - end -end - -function lists.registerplaced(dataset,tag) - renderings[dataset].used[tag] = true -end - -function lists.doifalreadyplaced(dataset,tag) - commands.doifelse(renderings[dataset].used[tag]) -end - --- we ask for <n>:tag but when we can't find it we go back --- to look for previous definitions, and when not found again --- we look forward - -local function compare(a,b) - local aa, bb = a and a[3], b and b[3] - return aa and bb and aa < bb -end - --- maybe hash subsets --- how efficient is this? old leftovers? - --- rendering ? - -local f_reference = formatters["r:%s:%s:%s"] -- dataset, instance (block), tag -local f_destination = formatters["d:%s:%s:%s"] -- dataset, instance (block), tag - -function lists.resolve(dataset,reference) -- maybe already feed it split - -- needs checking (the prefix in relation to components) - local subsets = nil - local block = tex.count.btxblock - local collected = references.collected - local prefix = nil -- todo: dataset ? - if prefix and prefix ~= "" then - subsets = { collected[prefix] or collected[""] } - else - local components = references.productdata.components - local subset = collected[""] - if subset then - subsets = { subset } - else - subsets = { } - end - for i=1,#components do - local subset = collected[components[i]] - if subset then - subsets[#subsets+1] = subset - end - end - end --- inspect(subsets) - if #subsets > 0 then - local result, nofresult, done = { }, 0, { } - for i=1,#subsets do - local subset = subsets[i] - for rest in gmatch(reference,"[^, ]+") do - local blk, tag, found = block, nil, nil - if block then - tag = f_destination(dataset,blk,rest) - found = subset[tag] - if not found then - for i=block-1,1,-1 do - tag = f_destination(dataset,blk,rest) --- tag = i .. ":" .. rest - found = subset[tag] - if found then - blk = i - break - end - end - end - end - if not found then - blk = "*" - tag = f_destination(dataset,blk,rest) - found = subset[tag] - end - if found then - local current = tonumber(found.entries and found.entries.text) -- tonumber needed - if current and not done[current] then - nofresult = nofresult + 1 - result[nofresult] = { blk, rest, current } - done[current] = true - end - end - end - end - local first, last, firsti, lasti, firstr, lastr - local collected, nofcollected = { }, 0 - for i=1,nofresult do - local r = result[i] - local current = r[3] - if not first then - first, last, firsti, lasti, firstr, lastr = current, current, i, i, r, r - elseif current == last + 1 then - last, lasti, lastr = current, i, r - else - if last > first + 1 then - nofcollected = nofcollected + 1 - collected[nofcollected] = { firstr, lastr } - else - nofcollected = nofcollected + 1 - collected[nofcollected] = firstr - if last > first then - nofcollected = nofcollected + 1 - collected[nofcollected] = lastr - end - end - first, last, firsti, lasti, firstr, lastr = current, current, i, i, r, r - end - end - if first and last then - if last > first + 1 then - nofcollected = nofcollected + 1 - collected[nofcollected] = { firstr, lastr } - else - nofcollected = nofcollected + 1 - collected[nofcollected] = firstr - if last > first then - nofcollected = nofcollected + 1 - collected[nofcollected] = lastr - end - end - end - if nofcollected > 0 then --- inspect(reference) --- inspect(result) --- inspect(collected) - for i=1,nofcollected do - local c = collected[i] - if i == nofcollected then - ctx_btxlistvariantparameter("lastpubsep") - elseif i > 1 then - ctx_btxlistvariantparameter("pubsep") - end - if #c == 3 then -- a range (3 is first or last) - ctx_btxdirectlink(f_reference(dataset,c[1],c[2]),c[3]) - else - local f, l = c[2], c[2] - ctx_btxdirectlink(f_reference(dataset,f[1],f[2]),f[3]) - context.endash() -- to do - ctx_btxdirectlink(f_reference(dataset,l[4],l[5]),l[6]) - end - end - else - context("[btx error 1]") - end - else - context("[btx error 2]") - end -end - -local done = { } - -function commands.btxreference(dataset,block,tag,data) - local ref = f_reference(dataset,block,tag) - if not done[ref] then - done[ref] = true --- context("<%s>",data) - ctx_dodirectfullreference(ref,data) - end -end - -local done = { } - -function commands.btxdestination(dataset,block,tag,data) - local ref = f_destination(dataset,block,tag) - if not done[ref] then - done[ref] = true --- context("<<%s>>",data) - ctx_dodirectfullreference(ref,data) - end -end - -commands.btxsetlistmethod = lists.setmethod -commands.btxresolvelistreference = lists.resolve -commands.btxregisterlistentry = lists.registerplaced -commands.btxaddtolist = lists.addentry -commands.btxcollectlistentries = lists.collectentries -commands.btxfetchlistentries = lists.fetchentries -commands.btxflushlistentries = lists.flushentries -commands.btxdoifelselistentryplaced = lists.doifalreadyplaced - -local citevariants = { } -publications.citevariants = citevariants - --- helper - -local function sortedtags(dataset,list,sorttype) - local luadata = datasets[dataset].luadata - local valid = { } - for i=1,#list do - local tag = list[i] - local entry = luadata[tag] - if entry then - local key = entry[sorttype] - if key then - valid[#valid+1] = { - tag = tag, - split = sortsplitter(sortstripper(key)) - } - else - end - end - end - if #valid == 0 or #valid ~= #list then - return list - else - sorters.sort(valid,basicsorter) - for i=1,#valid do - valid[i] = valid[i].tag - end - return valid - end -end - --- todo: standard : current - -local prefixsplitter = lpeg.splitat("::") - -function commands.btxhandlecite(dataset,tag,mark,variant,sorttype,setup) -- variant for tracing - local prefix, rest = lpegmatch(prefixsplitter,tag) - if rest then - dataset = prefix - else - rest = tag - end - ctx_setvalue("currentbtxdataset",dataset) - local tags = settings_to_array(rest) - if #tags > 0 then - if sorttype and sorttype ~= "" then - tags = sortedtags(dataset,tags,sorttype) - end - ctx_btxcitevariantparameter(v_left) - for i=1,#tags do - local tag = tags[i] - ctx_setvalue("currentbtxtag",tag) - if i > 1 then - ctx_btxcitevariantparameter(v_middle) - end - if mark ~= false then - ctx_btxdomarkcitation(dataset,tag) - end - ctx_directsetup(setup) -- cite can become alternative - end - ctx_btxcitevariantparameter(v_right) - else - -- error - end -end - -function commands.btxhandlenocite(dataset,tag,mark) - if mark ~= false then - local prefix, rest = lpegmatch(prefixsplitter,tag) - if rest then - dataset = prefix - else - rest = tag - end - ctx_setvalue("currentbtxdataset",dataset) - local tags = settings_to_array(rest) - for i=1,#tags do - ctx_btxdomarkcitation(dataset,tags[i]) - end - end -end - -function commands.btxcitevariant(dataset,block,tags,variant) - local action = citevariants[variant] or citevariants.default - if action then - action(dataset,tags,variant) - end -end - -function citevariants.default(dataset,tags,variant) - local content = getfield(dataset,tags,variant) - if content then - context(content) - end -end - --- todo : sort --- todo : choose between publications or commands namespace --- todo : use details.author --- todo : sort details.author - -local function collectauthoryears(dataset,tags) - local luadata = datasets[dataset].luadata - local list = settings_to_array(tags) - local found = { } - local result = { } - local order = { } - for i=1,#list do - local tag = list[i] - local entry = luadata[tag] - if entry then - local year = entry.year - local author = entry.author - if author and year then - local a = found[author] - if not a then - a = { } - found[author] = a - order[#order+1] = author - end - local y = a[year] - if not y then - y = { } - a[year] = y - end - y[#y+1] = tag - end - end - end - -- found = { author = { year_1 = { e1, e2, e3 } } } - for i=1,#order do - local author = order[i] - local years = found[author] - local yrs = { } - for year, entries in next, years do - if subyears then - -- -- add letters to all entries of an author and if so shouldn't - -- -- we tag all years of an author as soon as we do this? - -- if #entries > 1 then - -- for i=1,#years do - -- local entry = years[i] - -- -- years[i] = year .. string.char(i + string.byte("0") - 1) - -- end - -- end - else - yrs[#yrs+1] = year - end - end - result[i] = { author = author, years = yrs } - end - return result, order -end - --- (name, name and name) .. how names? how sorted? --- todo: we loop at the tex end .. why not here --- \cite[{hh,afo},kvm] - --- maybe we will move this tex anyway - -function citevariants.author(dataset,tags) - local result, order = collectauthoryears(dataset,tags,method,what) -- we can have a collectauthors - publications.citeconcat(order) -end - -local function authorandyear(dataset,tags,formatter) - local result, order = collectauthoryears(dataset,tags,method,what) -- we can have a collectauthors - for i=1,#result do - local r = result[i] - order[i] = formatter(r.author,r.years) -- reuse order - end - publications.citeconcat(order) -end - -function citevariants.authoryear(dataset,tags) - authorandyear(dataset,tags,formatters["%s (%, t)"]) -end - -function citevariants.authoryears(dataset,tags) - authorandyear(dataset,tags,formatters["%s, %, t"]) -end - -function citevariants.authornum(dataset,tags) - local result, order = collectauthoryears(dataset,tags,method,what) -- we can have a collectauthors - publications.citeconcat(order) - ctx_btxcitevariantparameter(v_inbetween) - lists.resolve(dataset,tags) -- left/right ? -end - --- function citevariants.short(dataset,tags) --- local short = getdetail(dataset,tags,"short") --- if short then --- context(short) --- end --- end - -function citevariants.short(dataset,tags) - local short = getdetail(dataset,tags,"short") - local suffix = getdetail(dataset,tags,"suffix") - if suffix then - context(short .. suffix) - elseif short then - context(short) - end -end - -function citevariants.page(dataset,tags) - local pages = getdetail(dataset,tags,"pages") - if not pages then - -- nothing - elseif type(pages) == "table" then - context(pages[1]) - ctx_btxcitevariantparameter(v_inbetween) - context(pages[2]) - else - context(pages) - end -end - -function citevariants.num(dataset,tags) --- ctx_btxdirectlink(f_destination(dataset,block,tags),listindex) -- not okay yet - lists.resolve(dataset,tags) -end - -function citevariants.serial(dataset,tags) -- the traditional fieldname is "serial" and not "index" - local index = getfield(dataset,tags,"index") - if index then - context(index) - end -end - --- List variants - -local listvariants = { } -publications.listvariants = listvariants - --- function commands.btxhandlelist(dataset,block,tag,variant,setup) --- if sorttype and sorttype ~= "" then --- tags = sortedtags(dataset,tags,sorttype) --- end --- ctx_setvalue("currentbtxtag",tag) --- ctx_btxlistvariantparameter(v_left) --- ctx_directsetup(setup) --- ctx_btxlistvariantparameter(v_right) --- end - -function commands.btxlistvariant(dataset,block,tags,variant,listindex) - local action = listvariants[variant] or listvariants.default - if action then - action(dataset,block,tags,variant,tonumber(listindex) or 0) - end -end - -function listvariants.default(dataset,block,tags,variant) - context("?") -end - -function listvariants.num(dataset,block,tags,variant,listindex) - ctx_btxdirectlink(f_destination(dataset,block,tags),listindex) -- not okay yet -end - --- function listvariants.short(dataset,block,tags,variant,listindex) --- local short = getdetail(dataset,tags,variant,variant) --- if short then --- context(short) --- end --- end - -function listvariants.short(dataset,block,tags,variant,listindex) - local short = getdetail(dataset,tags,"short","short") - local suffix = getdetail(dataset,tags,"suffix","suffix") - if suffix then - context(short .. suffix) - elseif short then - context(short) - end -end diff --git a/tex/context/base/publ-ini.mkiv b/tex/context/base/publ-ini.mkiv deleted file mode 100644 index 42226695c..000000000 --- a/tex/context/base/publ-ini.mkiv +++ /dev/null @@ -1,963 +0,0 @@ -%D \module -%D [ file=publ-ini, -%D version=2013.05.12, -%D title=\CONTEXT\ Publication Support, -%D subtitle=Initialization, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -% todo: we cannot use 'default' as this wipes metadata names (maybe no longer do that) -% todo: \v!cite => \s!cite -% todo: interface with (ml)bibtex (export -> call -> import) -% todo: check if 'all' etc are ok ... either use list or use other criterium - -% \definecolor[btx:field] [darkred] -% \definecolor[btx:crossref][darkblue] -% \definecolor[btx:key] [darkgreen] -% \definecolor[btx:todo] [darkyellow] - -%D We operate on several axis: -%D -%D \startitemize[packed] -%D \startitem we can have several databases (or combinations) \stopitem -%D \startitem we can add entries to them if needed (coded in tex) \stopitem -%D \startitem we can have several lists each using one of the databases \stopitem -%D \startitem we can render each list or citation independently \stopitem -%D \stopitemize -%D -%D We assume that the rendering of a list entry is consistent in a document, -%D although one can redefine properties if needed. Adding more granularity would -%D complicate the user interface beyond comprehension. - -\writestatus{loading}{ConTeXt Publication Support / Initialization} - -\registerctxluafile{publ-dat}{1.001} -\registerctxluafile{publ-aut}{1.001} -\registerctxluafile{publ-usr}{1.001} -\registerctxluafile{publ-ini}{1.001} -\registerctxluafile{publ-oth}{1.001} % this could become an option - -\unprotect - -\def\s!btx{btx} -\def\v!btxlist{btxlist} - -% a dedicated construction mechanism - -\installcorenamespace {btxlist} - -\installcommandhandler \??btxlist {btxlist} \??btxlist - -\unexpanded\setvalue{\??constructioninitializer\v!btxlist}% - {\let\currentbtxlist \currentconstruction - \let\constructionparameter \btxlistparameter - \let\detokenizedconstructionparameter\detokenizedbtxlistparameter - \let\letconstructionparameter \letbtxlistparameter - \let\useconstructionstyleandcolor \usebtxliststyleandcolor - \let\setupcurrentconstruction \setupcurrentbtxlist} - -\expandafter\let\csname\??constructionmainhandler \v!btxlist\expandafter\endcsname\csname\??constructionmainhandler \v!construction\endcsname -\expandafter\let\csname\??constructioncommandhandler\v!btxlist\expandafter\endcsname\csname\??constructioncommandhandler\v!construction\endcsname -\expandafter\let\csname\??constructiontexthandler \v!btxlist\expandafter\endcsname\csname\??constructiontexthandler \v!construction\endcsname - -\unexpanded\setvalue{\??constructioncommandhandler\v!btxlist}% - {\csname\??constructionstarthandler\v!construction\endcsname - \csname\??constructionstophandler \v!construction\endcsname - \endgroup} - -\unexpanded\setvalue{\??constructionstarthandler\v!btxlist}% - {\csname\??constructionstarthandler\v!construction\endcsname} - -\unexpanded\setvalue{\??constructionstophandler\v!btxlist}% - {\csname\??constructionstophandler\v!construction\endcsname - \endgroup} - -\unexpanded\def\startbtxlistentry#1% - {\begingroup - \strc_constructions_initialize{#1}% - \csname\??constructionstarthandler\currentconstructionhandler\endcsname} - -\unexpanded\def\stopbtxlistentry - {\csname\??constructionstophandler\currentconstructionhandler\endcsname} - -\unexpanded\setvalue{\??constructiontexthandler\v!btxlist}% - {\begingroup - \useconstructionstyleandcolor\c!headstyle\c!headcolor % move to \currentconstructiontext - \the\everyconstruction - \constructionparameter\c!headcommand - {\strut - \constructionparameter\c!text - \btx_reference_inject}% - \endgroup} - -\unexpanded\def\strc_constructions_initialize#1% class instance - {\edef\currentconstruction{#1}% - \let\currentconstructionlistentry\!!zerocount - \expandafter\let\expandafter\currentconstructionmain \csname\??constructionmain \currentconstruction\endcsname - \expandafter\let\expandafter\currentconstructionlevel \csname\??constructionlevel\currentconstruction\endcsname - \expandafter\let\expandafter\currentconstructionhandler\csname\??constructionclass\currentconstruction\endcsname - \csname\??constructioninitializer\currentconstructionhandler\endcsname} - -\appendtoks - % \ifx\currentbtxlistparent\empty - % \defineconstruction[\currentbtxlist][\currentbtxlistparent][\s!handler=\v!btxlist,\c!level=1]% - % \else - % \defineconstruction[\currentbtxlist][\s!handler=\v!btxlist,\c!level=1]% - % \fi - \ifx\currentbtxlistparent\empty - \letvalue{\??constructionmain\currentbtxlist}\currentbtxlist - \else - \letvalue{\??constructionmain\currentbtxlist}\currentbtxlistparent - \fi - \setevalue{\??constructionlevel\currentbtxlist}{\number\btxlistparameter\c!level}% - \setevalue{\??constructionclass\currentbtxlist}{\btxlistparameter\s!handler}% -\to \everydefinebtxlist - -\setupbtxlist - [\s!handler=\v!btxlist, - \c!level=1] - -\setupbtxlist - [\c!alternative=\v!left, - \c!headstyle=, - \c!titlestyle=, - %\c!style=, - %\c!color=, - %\c!headcolor=, - %\c!titlecolor=, - \c!width=4\emwidth, - \c!distance=\emwidth, - %\c!titledistance=.5\emwidth, - %\c!hang=, - %\c!sample=, - %\c!align=, - %\c!headalign=, - \c!margin=\v!no, - \c!before=\blank, - \c!inbetween=\blank, - \c!after=\blank, - %\c!indentnext=\v!yes, - %\c!indenting=\v!never, - %\c!titleleft=(, - %\c!titleright=), - %\c!closesymbol=, - %\c!closecommand=\wordright, - \c!display=\v!yes, - \c!command=, - %\c!titlecommand=, - %\c!expansion=\v!no, - %\c!xmlsetup=, - %\s!catcodes=, - %\c!title=\v!yes, - %\c!text=, - ] - -% here starts the bib stuff - -\installcorenamespace {btxdataset} -\installcorenamespace {btxlistvariant} -\installcorenamespace {btxcitevariant} -\installcorenamespace {btxrendering} -\installcorenamespace {btxcommand} -\installcorenamespace {btxnumbering} - -\installcommandhandler \??btxdataset {btxdataset} \??btxdataset -\installcommandhandler \??btxlistvariant {btxlistvariant} \??btxlistvariant -\installcommandhandler \??btxcitevariant {btxcitevariant} \??btxcitevariant -\installcommandhandler \??btxrendering {btxrendering} \??btxrendering - -\unexpanded\def\usebtxdataset - {\dodoubleargument\publ_use_dataset} - -\def\publ_use_dataset[#1][#2]% - {\ifsecondargument - \ctxcommand{usebtxdataset("#1","#2")}% - \else - \ctxcommand{usebtxdataset("\v!standard","#1")}% - \fi} - -\definebtxdataset - [\v!standard] - -% \usebtxdataset -% [standard] -% [mybibs.bib] - -\unexpanded\def\startpublication - {\dodoubleempty\publ_set_publication} - -\let\stoppublication\relax - -\def\publ_set_publication[#1][#2]% - {\begingroup - \catcode\commentasciicode\othercatcode - \ifsecondargument - \expandafter\publ_set_publication_indeed - \else\iffirstargument - \doubleexpandafter\publ_set_publication_checked - \else - \doubleexpandafter\publ_set_publication_default - \fi\fi{#1}{#2}} - -\def\publ_set_publication_default#1#2% - {\publ_set_publication_indeed\v!standard{#1}} - -\def\publ_set_publication_checked#1#2% - {\doifassignmentelse{#1} - {\publ_set_publication_indeed\v!standard{#1}} - {\publ_set_publication_indeed{#1}{}}} - -\def\publ_set_publication_indeed#1#2#3\stoppublication - {\ctxcommand{addbtxentry("#1",\!!bs#2\!!es,\!!bs\detokenize{#3}\!!es)}% - \endgroup - \ignorespaces} - -% commands - -\unexpanded\def\btxcommand#1% - {\ifcsname\??btxcommand#1\endcsname - \expandafter\publ_command_yes - \else - \expandafter\publ_command_nop - \fi{#1}} - -\let\btxcmd\btxcommand - -\def\publ_command_yes#1% - {\csname\??btxcommand#1\endcsname} - -\def\publ_command_nop#1% - {\ifcsname#1\endcsname - \writestatus\m!publications{unknown command: #1, using built-in context variant #1}% - %\setuxvalue{\??btxcommand#1}{\expandafter\noexpand\csname#1\endcsname}% - \global\expandafter\let\csname\??btxcommand#1\expandafter\endcsname\csname#1\endcsname - \else\ifcsname\utfupper{#1}\endcsname - \writestatus\m!publications{unknown command: #1, using built-in context variant \utfupper{#1}}% - %\setuxvalue{\??btxcommand#1}{\expandafter\noexpand\csname\utfupper{#1}\endcsname}% - \global\expandafter\let\csname\??btxcommand#1\expandafter\endcsname\csname\utfupper{#1}\endcsname - \else - \writestatus\m!publications{unknown command: #1}% - \setugvalue{\??btxcommand#1}{\underbar{\tttf#1}}% - \fi\fi - \publ_command_yes{#1}} - -\unexpanded\def\definebtxcommand#1% {body} #1..#n{body} - {\setuvalue{\??btxcommand\strippedcsname#1}}% - -% access - -\let\currentbtxtag \empty -\let\currentbtxdataset\v!standard - -\unexpanded\def\setbtxdataset[#1]% - {\edef\currentbtxdataset{\ctxcommand{setbtxdataset("#1")}}} - -\unexpanded\def\setbtxentry[#1]% - {\edef\currentbtxtag{\ctxcommand{setbtxentry("\currentbtxdataset","#1")}}} - -% \let\btxsetdataset\setbtxdataset -% \let\btxsetentry \setbtxentry - -\def\btxfield #1{\ctxcommand{btxfield("\currentbtxdataset","\currentbtxtag","#1")}} -\def\btxdetail #1{\ctxcommand{btxdetail("\currentbtxdataset","\currentbtxtag","#1")}} -\def\btxflush #1{\ctxcommand{btxflush("\currentbtxdataset","\currentbtxtag","#1")}} -%def\btxrendering#1{\ctxcommand{btxrendering("\currentbtxdataset","\currentbtxtag","#1","\btxrenderingparameter\c!interaction")}} -\def\btxdoifelse #1{\ctxcommand{btxdoifelse("\currentbtxdataset","\currentbtxtag","#1")}} -\def\btxdoif #1{\ctxcommand{btxdoif("\currentbtxdataset","\currentbtxtag","#1")}} -\def\btxdoifnot #1{\ctxcommand{btxdoifnot("\currentbtxdataset","\currentbtxtag","#1")}} - -\let\btxsetup \directsetup - -%D How complex will we go? Can we assume that e.g. an apa style will not be mixed -%D with another one? I think this assumption is okay. For manuals we might want to -%D mix but we can work around it. - -%D Rendering. - -\unexpanded\def\btxspace {\removeunwantedspaces\space} -\unexpanded\def\btxperiod {\removeunwantedspaces.\space} -\unexpanded\def\btxcomma {\removeunwantedspaces,\space} -\unexpanded\def\btxlparent {\removeunwantedspaces\space(} -\unexpanded\def\btxrparent {\removeunwantedspaces)\space} -\unexpanded\def\btxlbracket{\removeunwantedspaces\space[} -\unexpanded\def\btxrbracket{\removeunwantedspaces]\space} - -%D Rendering lists and citations. - -\newconditional\c_btx_trace - -\installtextracker - {btxrendering} - {\settrue \c_btx_trace} - {\setfalse\c_btx_trace} - -\unexpanded\def\startbtxrendering - {\begingroup - \dosingleempty\btx_start_rendering} - -\def\btx_start_rendering[#1]% - {\edef\currentbtxrendering{#1}} - -\unexpanded\def\stopbtxrendering - {\endgroup} - -\unexpanded\def\btxtodo#1% - {[#1]} - -%D Specific rendering definitions (like apa): - -\unexpanded\def\loadbtxdefinitionfile[#1]% - {\ctxcommand{loadbtxdefinitionfile("#1")}} - -%D Lists: - -\newdimen\d_publ_number_width -%newdimen\d_publ_number_distance - -\ifdefined\btxblock \else \newcount\btxblock \fi \btxblock\plusone -\ifdefined\btxcounter \else \newcount\btxcounter \fi - -\newtoks \everysetupbtxlistplacement % name will change -\newtoks \everysetupbtxciteplacement % name will change - -% \def\publ_list_processor % bibref -> btx (old method, keep as reference) -% {\ctxcommand{btxaddtolist("\currentbtxrendering",\currentlistindex,"btxref")}} - -\definelist % only used for selecting - [btx] - -\setuplist - [btx]% - [\c!state=\v!start]% - -\appendtoks - \ifx\currentbtxrenderingparent\empty - \definebtxlist - [\currentbtxrendering]% - \else - \definebtxlist - [\currentbtxrendering]% - [\currentbtxrenderingparent]% - \fi -\to \everydefinebtxrendering - -\unexpanded\def\btx_entry_inject - {\begingroup - \edef\currentbtxcategory{\btxfield{category}}% - \ignorespaces - \directsetup{\s!btx:\currentbtxalternative:\currentbtxcategory}% - \removeunwantedspaces - \endgroup} - -\unexpanded\def\completebtxrendering{\dodoubleempty\publ_place_list_complete} -\unexpanded\def\placebtxrendering {\dodoubleempty\publ_place_list_standard} - -\let\completelistofpublications\completebtxrendering -\let\placelistofpublications \placebtxrendering - -\def\publ_place_list_check_criterium - {\edef\currentbtxcriterium{\btxrenderingparameter\c!criterium}% \v!cite will become \s!cite - \ifx\currentbtxcriterium\empty - \let\currentbtxcriterium\v!previous - \else\ifx\currentbtxcriterium\v!cite - \let\currentbtxcriterium\v!here - \fi\fi} - -\def\publ_place_list_complete[#1][#2]% title might become obsolete, just headtext - {\begingroup - \edef\currentbtxrendering{#1}% - \setupcurrentbtxrendering[#2]% - \let\currentlist\s!btx - \let\currentbtxlist\currentbtxrendering - \publ_place_list_check_criterium - \edef\currentbtxrenderingtitle{\btxrenderingparameter\c!title}% - \ifx\currentbtxrenderingtitle\empty - \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbtxrendering,\c!title={\headtext{\currentbtxrendering}}]}% - \else - \normalexpanded{\startnamedsection[\v!chapter][\c!reference=\currentbtxrendering,\c!title={\currentbtxrenderingtitle}]}% - \fi - \publ_place_list_indeed - \stopnamedsection - \endgroup} - -\def\publ_place_list_standard[#1][#2]% - {\begingroup - \edef\currentbtxrendering{#1}% - \setupcurrentbtxrendering[#2]% - \let\currentlist\s!btx - \let\currentbtxlist\currentbtxrendering - \publ_place_list_check_criterium - \publ_place_list_indeed - \endgroup} - -\newconditional\c_publ_place_all -\newconditional\c_publ_place_register % to be interfaced -\newconditional\c_publ_place_check % to be interfaced - -\appendtoks - \ifx\currentbtxcriterium\v!all % move this check to lua ... easier to test there anyway - \settrue\c_publ_place_all - \else - \setfalse\c_publ_place_all - \fi -\to \everysetupbtxlistplacement - -\def\publ_place_list_indeed - {\startbtxrendering[\currentbtxrendering]% - \directsetup{\btxrenderingparameter\c!setups}% - % \determinelistcharacteristics[\currentbtxrendering]% - \edef\currentbtxalternative{\btxrenderingparameter\c!alternative}% - \edef\currentbtxdataset{\btxrenderingparameter\c!dataset}% - \let\currentlist\s!btx - \let\currentbtxlist\currentbtxrendering - \the\everysetupbtxlistplacement - \forgetall - \ctxcommand{btxsetlistmethod("\currentbtxdataset","\btxrenderingparameter\c!method")}% - \startpacked[\v!blank]% - % here we just collect items - \ctxcommand{btxcollectlistentries { - names = "btx", - criterium = "\currentbtxcriterium", - number = "\btxrenderingparameter\c!number", - btxdataset = "\currentbtxdataset", - keyword = "\btxrenderingparameter\c!keyword", - }}% - % next we analyze the width - \ifx\btx_reference_inject_indeed\relax \else - \edef\p_width{\btxrenderingparameter\c!width}% - \ifx\p_width\v!auto - \scratchcounter\btxcounter - \setbox\scratchbox\vbox{\settrialtypesetting\ctxcommand{btxfetchlistentries("\currentbtxdataset")}}% - \d_publ_number_width\wd\scratchbox - \global\btxcounter\scratchcounter - \letbtxlistparameter\c!width\d_publ_number_width - \fi - \fi - % this actually typesets them - \ctxcommand{btxflushlistentries("\currentbtxdataset","\btxrenderingparameter\c!sorttype")}% - \stoppacked - \stopbtxrendering - \global\advance\btxblock\plusone} - -\def\currentbtxblock{\number\btxblock} - -\def\publ_place_list_entry_checked - {\ctxcommand{btxdoifelselistentryplaced("\currentbtxdataset","\currentbtxtag")}\donothing\publ_place_list_entry} - -\def\publ_place_list_entry_register - {\ctxcommand{btxregisterlistentry("\currentbtxdataset","\currentbtxtag")}} - -\unexpanded\def\btxhandlelistentry#1% called at the lua end - {\begingroup - \edef\currentbtxtag{#1}% - \ifconditional\c_publ_place_all - \publ_place_list_entry - \else\ifconditional\c_publ_place_check - \publ_place_list_entry_checked - \else - \publ_place_list_entry - \fi\fi - \endgroup} - -\unexpanded\def\publ_place_list_entry - {\global\advance\btxcounter\plusone - \ifconditional\c_publ_place_register - \publ_place_list_entry_register - \fi - \let\currentlist\s!btx - \startbtxlistentry\currentbtxrendering - \btx_entry_inject - \stopbtxlistentry} - -\unexpanded\def\btxchecklistentry#1% called at the lua end - {\begingroup - \edef\currentbtxtag{#1}% - \ifx\currentbtxcriterium\v!all % move this check to lua ... easier to test there anyway - \publ_check_list_entry - \else - \ctxcommand{btxdoifelselistentryplaced("\currentbtxdataset","\currentbtxtag")}\donothing\publ_check_list_entry - \fi - \endgroup} - -\unexpanded\def\publ_check_list_entry - {\global\advance\btxcounter\plusone - % todo, switch to font - \hbox{\btx_reference_checked}% - \par} - -\unexpanded\def\btx_reference_inject % we can use a faster \reference - {\dontleavehmode\begingroup % no box - \iftrialtypesetting\else - \ctxcommand{btxdestination("\currentbtxdataset","\currentbtxblock","\currentbtxtag","\number\btxcounter")}% - \fi - \btx_reference_inject_indeed - \endgroup} - -\unexpanded\def\btx_reference_checked - {\dontleavehmode\hbox\bgroup - \btx_reference_inject_indeed - \egroup} - -\setuvalue{\??btxnumbering\v!short }{\btxlistvariant{short}} % these will be setups -\setuvalue{\??btxnumbering\v!bib }{\btxlistvariant{num}} % these will be setups -\setuvalue{\??btxnumbering\s!unknown}{\btxlistvariant{num}} % these will be setups -\setuvalue{\??btxnumbering\v!yes }{\btxlistvariant{num}} % these will be setups - -\appendtoks - \edef\p_btx_numbering{\btxrenderingparameter\c!numbering}% - \letlistparameter\c!numbercommand\firstofoneargument % for the moment, no doubling needed - \ifx\p_btx_numbering\v!no - \letlistparameter\c!textcommand\outdented % needed? we can use titlealign - \letlistparameter\c!symbol \v!none - \letlistparameter\c!aligntitle \v!yes - \let\btx_reference_inject_indeed\relax - \else - \ifcsname\??btxnumbering\p_btx_numbering\endcsname \else - \let\p_btx_numbering\s!unknown - \fi - \letlistparameter\c!headnumber\v!always - \expandafter\let\expandafter\btx_reference_inject_indeed\csname\??btxnumbering\p_btx_numbering\endcsname - \fi -\to \everysetupbtxlistplacement - -% \appendtoks -% \edef\currentbtxcriterium{\btxrenderingparameter\c!criterium}% -% \to \everysetupbtxlistplacement - -\unexpanded\def\btxflushauthor - {\doifnextoptionalelse\btx_flush_author_yes\btx_flush_author_nop} - -\def\btx_flush_author_yes[#1]{\btx_flush_author{#1}} -\def\btx_flush_author_nop {\btx_flush_author{\btxlistvariantparameter\c!author}} - -\unexpanded\def\btx_flush_author#1#2% - {\edef\currentbtxfield{#2}% - \let\currentbtxlistvariant\currentbtxfield - \ctxcommand{btxauthor("\currentbtxdataset","\currentbtxtag","\currentbtxfield",{ - combiner = "#1", - etallimit = \number\btxlistvariantparameter\c!etallimit, - etaldisplay = \number\btxlistvariantparameter\c!etaldisplay, - })}} - -\unexpanded\def\btxflushauthornormal {\btx_flush_author{normal}} % #1 -\unexpanded\def\btxflushauthornormalshort {\btx_flush_author{normalshort}} % #1 -\unexpanded\def\btxflushauthorinverted {\btx_flush_author{inverted}} % #1 -\unexpanded\def\btxflushauthorinvertedshort{\btx_flush_author{invertedshort}} % #1 - -% \btxflushauthor{author} -% \btxflushauthor{artauthor} -% \btxflushauthor{editor} -% -% \btxflushauthor[normal]{author} -% \btxflushauthor[normalshort]{author} -% \btxflushauthor[inverted]{author} -% \btxflushauthor[invertedshort]{author} - -% Interaction - -\newconditional\btxinteractive - -\unexpanded\def\btxdoifelseinteraction - {\iflocation - \edef\p_interaction{\btxcitevariantparameter\c!interaction}% - \ifx\p_interaction\v!stop - \doubleexpandafter\secondoftwoarguments - \else - \doubleexpandafter\firstoftwoarguments - \fi - \else - \expandafter\secondoftwoarguments - \fi} - -\appendtoks - \iflocation - \edef\p_interaction{\btxlistvariantparameter\c!interaction}% - \ifx\p_interaction\v!stop - \let\doifelsebtxinteractionelse\secondoftwoarguments - \setfalse\btxinteractive - \else - \let\doifelsebtxinteractionelse\firstoftwoarguments - \settrue\btxinteractive - \fi - \else - \let\doifelsebtxinteractionelse\secondoftwoarguments - \setfalse\btxinteractive - \fi -\to \everysetupbtxlistplacement - -% bib -> btx - -\unexpanded\def\btxgotolink#1[#2]{\doifreferencefoundelse{\bibrefprefix#2}{\goto{#1}[\bibrefprefix#2]}{#1}} -\unexpanded\def\btxatlink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\at [\bibrefprefix#1]}{#1}} -\unexpanded\def\btxinlink [#1]{\doifreferencefoundelse{\bibrefprefix#1}{\expanded{\goto{\currentreferencetext}}[\bibrefprefix#1]}{#1}} - -\unexpanded\def\btxdirectlink#1#2{\goto{#2 {\tttf[#1]}}[#1]} -\unexpanded\def\btxdirectlink#1#2{\goto{#2}[#1]} - -\let\gotobiblink\btxgotolink -\let\atbiblink \btxatlink -\let\inbiblink \btxinlink - -\unexpanded\def\btxnumberedreference[#1]% \bibtexnumref (replaced by \cite[num]) - {\dontleavehmode - \begingroup - \btxcitevariantparameter\v!left - \penalty\plustenthousand % todo - \ctxcommand{btxresolvelistreference("\currentbtxdataset","#1")}% todo: split dataset from #1, so another call - \btxcitevariantparameter\v!right - \endgroup} - -% \def\btxnumberedplaceholder[#1]% \nobibtexnumref -% {[#1]} - -\appendtoks - % for old times sake, for a while at least - \let\maybeyear\gobbleoneargument - \let\noopsort \gobbleoneargument -\to \everysetupbtxlistplacement - -\appendtoks - % for old times sake, for a while at least - \let\maybeyear\gobbleoneargument - \let\noopsort \gobbleoneargument -\to \everysetupbtxciteplacement - -\appendtoks - \doifnot{\btxrenderingparameter\c!continue}\v!yes - {\global\btxcounter\zerocount}% -\to \everysetupbtxlistplacement - -%D When a publication is cited, we need to signal that somehow. This is done with the -%D following (not user) command. We could tag without injecting a node but this way -%D we also store the location, which makes it possible to ask local lists. - -\newconditional\c_publ_cite_write - -% for reference, but split now done at the lua end -% -% \def\publ_cite_write#1% not used -% {\splitstring#1\at::\to\askedbtxrendering\and\askedbtxtag -% \ifx\askedbtxtag\empty -% \let\currentbtxtag \askedbtxrendering -% \else -% \let\currentbtxtag \askedbtxtag -% \let\currentbtxrendering\askedbtxrendering -% \fi -% \iftrialtypesetting \else -% \processcommacommand[\currentbtxtag]{\publ_cite_indeed\currentbtxrendering}% -% \fi} - -\def\publ_cite_indeed#1#2% - {\expanded{\writedatatolist[btx][btxset=#1,btxref=#2]}} - -\def\btxdomarkcitation#1#2% called from lua end - {\iftrialtypesetting \else - \writedatatolist[btx][btxset=#1,btxref=#2]% \c!location=\v!here - \fi} - -%D \macros{cite,nocite,citation,nocitation,usecitation} -%D -%D The inline \type {\cite} command creates a (often) short reference to a publication -%D and for historic reasons uses a strict test for brackets. This means, at least -%D in the default case that spaces are ignored in the argument scanner. The \type -%D {\citation} commands is more liberal but also gobbles following spaces. Both -%D commands insert a reference as well as a visual clue. -%D -%D The \type {no} commands all do the same (they are synonyms): they make sure that -%D a reference is injected but show nothing. However, they do create a node so best -%D attach them to some text in order to avoid spacing interferences. A slightly -%D less efficient alternative is \type {\cite[none][tag]}. - -% [tags] -% [settings|variant][tags] -% [base::tags] -% [settings|variant][base::tags] - -\unexpanded\def\btxcite - {\dontleavehmode - \begingroup - \strictdoifnextoptionalelse\publ_cite_tags_options\publ_cite_tags_indeed} - -\unexpanded\def\publ_cite_tags_indeed#1% - {\letinteractionparameter\c!style\empty - \edef\currentbtxcitevariant{\btxcitevariantparameter\c!alternative}% - \edef\currentbtxcitetag{#1}% - \publ_cite_variant - \endgroup} - -\let\publ_citation_tags_indeed\publ_cite_tags_indeed - -\unexpanded\def\publ_cite_tags_options[#1]% - {\strictdoifnextoptionalelse{\publ_cite_tags_options_indeed{#1}}{\publ_cite_tags_indeed{#1}}} - -\unexpanded\def\publ_cite_tags_options_indeed#1[#2]% - {\edef\currentbtxcitetag{#2}% - \doifassignmentelse{#1} - {\publ_cite_tags_settings_indeed{#1}} - {\publ_cite_tags_variants_indeed{#1}}} - -\def\publ_cite_tags_settings_indeed#1% - {\letinteractionparameter\c!style\empty - %\letinteractionparameter\c!color\empty - \getdummyparameters[\c!alternative=,\c!extras=,#1]% - \edef\p_alternative{\dummyparameter\c!alternative}% - \ifx\p_alternative\empty \else - \let\currentbtxcitevariant\p_alternative - \fi - \setupcurrentbtxcitevariantparameters[#1]% - \edef\p_extras{\dummyparameter\c!extras}% - \ifx\p_extras\empty \else - \edef\p_right{\btxcitevariantparameter\c!right}% - \ifx\p_right\empty \else - \setexpandedbtxcitevariantparameter\p_right{\p_extras\p_right}% - \fi - \fi - \publ_cite_variant - \endgroup} - -\def\publ_cite_tags_variants_indeed#1% - {\letinteractionparameter\c!style\empty - \edef\currentbtxcitevariant{#1}% - \publ_cite_variant - \endgroup} - -\newconditional\btxcitecompress - -\def\publ_cite_variant - {\edef\p_compress{\btxcitevariantparameter\c!compress}% - % \ifx\p_compress\v!no - % \setfalse\btxcitecompress - % \else - % \settrue\btxcitecompress - % \fi - \begingroup - \settrue\c_publ_cite_write - \publ_cite_handle_variant_indeed[\currentbtxcitetag]} - -\unexpanded\def\publ_cite_handle_variant#1% - {\begingroup - \the\everysetupbtxciteplacement - \edef\currentbtxcitevariant{#1}% - \dosingleargument\publ_cite_handle_variant_indeed} - -\def\publ_cite_handle_variant_indeed[#1]% - {\usebtxcitevariantstyleandcolor\c!style\c!color - \letbtxcitevariantparameter\c!alternative\currentbtxcitevariant - \ctxcommand{btxhandlecite(% - "\currentbtxdataset",% - "#1",% - \iftrialtypesetting false\else true\fi,% - "\currentbtxcitevariant",% - "\btxcitevariantparameter\c!sorttype",% - "\btxcitevariantparameter\c!setups"% - )}% - \endgroup} - -\unexpanded\def\btxcitation - {\dontleavehmode - \begingroup - \dodoubleempty\publ_citation} - -\def\publ_citation[#1][#2]% could be made more efficient but not now - {\ifsecondargument - \publ_cite_tags_options_indeed{#1}[#2]% - \else - \publ_cite_tags_indeed{#1}% - \fi} - -\unexpanded\def\btxnocite - {\dosingleempty\publ_cite_no} - -\unexpanded\def\publ_cite_no[#1]% - {\iftrialtypesetting \else - \ctxcommand{btxhandlenocite("\currentbtxdataset","#1",true)}% - \fi} - -%D Compatibility: - -\let\cite \btxcite -\let\citation \btxcitation -\let\nocite \btxnocite -\let\nocitation \btxnocite -\let\usepublication\btxnocite - -%D Cite helpers: - -\unexpanded\def\btxcitevariant#1% - {\ctxcommand{btxcitevariant("\currentbtxdataset","\currentbtxblock","\currentbtxtag","#1")}} - -%D List helpers: - -\def\currentbtxindex{0} - -\unexpanded\def\btxlistvariant#1% was \currentbtxindex - {\begingroup - \edef\currentbtxlistvariant{#1}% - \btxlistvariantparameter\c!left - \ctxcommand{btxlistvariant("\currentbtxdataset","\currentbtxblock","\currentbtxtag","#1","\number\btxcounter")}% some can go - \btxlistvariantparameter\c!right - \endgroup} - -%D Whatever helpers: - -\unexpanded\def\btxsingularplural#1% - {\ctxcommand{btxsingularorplural("\currentbtxdataset","\currentbtxtag","#1")}} - -\let\btxsingularorplural\btxsingularplural - -%D Loading variants: - -\appendtoks - \loadbtxdefinitionfile[\btxrenderingparameter\c!alternative] -\to \everysetupbtxrendering - -%D Defaults: - -\setupbtxrendering - [\c!dataset=\v!standard, - \c!method=\v!global, - \c!setups=btx:rendering:\btxrenderingparameter\c!alternative, - \c!alternative=apa, - \c!sorttype=, - \c!criterium=, - \c!refcommand=authoryears, % todo - \c!numbering=\v!yes, -% \c!autohang=\v!no, - \c!width=\v!auto, - \c!distance=1.5\emwidth] - -\definebtxrendering - [\v!standard] - -\setupbtxcitevariant - [\c!interaction=\v!start, - \c!setups=btx:cite:\btxcitevariantparameter\c!alternative, - \c!alternative=num, - \c!andtext={ and }, - \c!otherstext={ et al.}, - \c!pubsep={, }, - \c!lastpubsep={ and }, - \c!compress=\v!no, - \c!inbetween={ }, - \c!left=, - \c!right=] - -\definebtxcitevariant - [author] - [%c!sorttype=, - \c!left={(}, - \c!middle={, }, - \c!right={)}] - -\definebtxcitevariant - [authoryear] - [\c!compress=\v!yes, - \c!inbetween={, }, - \c!left={(}, - \c!middle={, }, - \c!right={)}] - -\definebtxcitevariant - [authoryears] - [authoryear] - -\definebtxcitevariant - [authornum] - [author] - [\c!left={[}, - \c!right={]}] - -\definebtxcitevariant - [year] - [\c!left={(}, - \c!right={)}] - -\definebtxcitevariant - [key] - [\c!left={[}, - \c!right={]}] - -\definebtxcitevariant - [serial] - [\c!left={[}, - \c!right={]}] - -\definebtxcitevariant - [page] - [\c!left={[}, - \c!right={]}] - -\definebtxcitevariant - [short] - [\c!left={[}, - \c!right={]}] - -\definebtxcitevariant - [type] - [\c!left={[}, - \c!right={]}] - -\definebtxcitevariant - [doi] - [\c!left={[}, - \c!right={]}] - -\definebtxcitevariant - [url] - [\c!left={[}, - \c!right={]}] - -\definebtxcitevariant - [page] - [\c!left=, - \c!right=, - \c!inbetween=\endash] - -\definebtxcitevariant - [num] - [\c!compress=\v!yes, - \c!inbetween={--}, - \c!left={[}, - \c!right={]}] - -\setupbtxlistvariant - [\c!namesep={, }, - \c!lastnamesep={ and }, - \c!finalnamesep={ and }, - \c!firstnamesep={ }, - \c!juniorsep={ }, - \c!vonsep={ }, - \c!surnamesep={, }, - \c!surnameinitialsep={, }, - \c!surnamefirstnamesep={, }, - \c!etallimit=5, - \c!etaldisplay=5, - \c!etaltext={ et al.}, - \c!monthconversion=\v!number, - \c!authorconversion=\v!normal] - -\definebtxlistvariant - [author] - [author=invertedshort] % we could also do this in the apa style itself - -\definebtxlistvariant - [editor] - [author] - -\definebtxlistvariant - [artauthor] - [author] - -% Do we want these in the format? Loading them delayed is somewhat messy. - -\loadbtxdefinitionfile[apa] -\loadbtxdefinitionfile[cite] -\loadbtxdefinitionfile[commands] -\loadbtxdefinitionfile[definitions] - -\protect diff --git a/tex/context/base/publ-old.mkiv b/tex/context/base/publ-old.mkiv deleted file mode 100644 index f616428e6..000000000 --- a/tex/context/base/publ-old.mkiv +++ /dev/null @@ -1,22 +0,0 @@ -%D \module -%D [ file=publ-old, -%D version=2013.12.24, -%D title=\CONTEXT\ Publication Support, -%D subtitle=Old Fashioned \BIBTEX, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\unprotect - -% we could use runtime commands instead - -\unexpanded\def\setupbibtex {\usemodule[oldbibtex]\setupbibtex} -\unexpanded\def\setuppublications {\usemodule[oldbibtex]\setuppublications} -\unexpanded\def\setuppublicationlist{\usemodule[oldbibtex]\setuppublicationlist} - -\protect diff --git a/tex/context/base/publ-oth.lua b/tex/context/base/publ-oth.lua deleted file mode 100644 index 14da19f9c..000000000 --- a/tex/context/base/publ-oth.lua +++ /dev/null @@ -1,146 +0,0 @@ -if not modules then modules = { } end modules ['publ-oth'] = { - version = 1.001, - comment = "this module part of publication support", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local P, S, C, Ct, Cf, Cg, Cmt, Carg = lpeg.P, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.Cmt, lpeg.Carg -local lpegmatch = lpeg.match - -local p_endofline = lpeg.patterns.newline - -local loaders = publications.loaders -local getindex = publications.getindex - -local function addfield(t,k,v,fields) - k = fields[k] - if k then - local tk = t[k] - if tk then - t[k] = tk .. " and " .. v - else - t[k] = v - end - end - return t -end - -local function checkfield(_,_,t,categories,all) - local tag = t.tag - if tag then - local category = t.category - t.tag = nil - t.category = categories[category] or category - all[tag] = t - end - return true -end - --- endnotes -- - -local fields = { - ["@"] = "tag", - ["0"] = "category", - ["A"] = "author", - ["E"] = "editor", - ["T"] = "title", - ["D"] = "year", - ["I"] = "publisher", -} - -local categories = { - ["Journal Article"] = "article", -} - -local entry = P("%") * Cg(C(1) * (S(" \t")^1) * C((1-p_endofline)^0) * Carg(1)) * p_endofline -local record = Cf(Ct("") * (entry^1), addfield) -local records = (Cmt(record * Carg(2) * Carg(3), checkfield) * P(1))^1 - -function publications.endnotes_to_btx(data) - local all = { } - lpegmatch(records,data,1,fields,categories,all) - return all -end - -function loaders.endnote(dataset,filename) - -- we could combine the next into checkfield but let's not create too messy code - loaders.lua(dataset,publications.endnotes_to_btx(io.loaddata(filename) or "")) -end - --- refman -- - -local entry = Cg(C((1-lpeg.S(" \t")-p_endofline)^1) * (S(" \t-")^1) * C((1-p_endofline)^0) * Carg(1)) * p_endofline -local record = Cf(Ct("") * (entry^1), addfield) -local records = (Cmt(record * Carg(2) * Carg(3), checkfield) * P(1))^1 - -local fields = { - ["SN"] = "tag", - ["TY"] = "category", - ["A1"] = "author", - ["E1"] = "editor", - ["T1"] = "title", - ["Y1"] = "year", - ["PB"] = "publisher", -} - -local categories = { - ["JOUR"] = "article", -} - -function publications.refman_to_btx(data) - local all = { } - lpegmatch(records,data,1,fields,categories,all) - return all -end - -function loaders.refman(dataset,filename) - -- we could combine the next into checkfield but let's not create too messy code - loaders.lua(dataset,publications.refman_to_btx(io.loaddata(filename) or "")) -end - --- test -- - --- local endnote = [[ --- %0 Journal Article --- %T Scientific Visualization, Overviews, Methodologies, and Techniques --- %A Nielson, Gregory M --- %A Hagen, Hans --- %A Müller, Heinrich --- %@ 0818677776 --- %D 1994 --- %I IEEE Computer Society --- --- %0 Journal Article --- %T Scientific Visualization, Overviews, Methodologies, and Techniques --- %A Nielson, Gregory M --- %A Hagen, Hans --- %A Müller, Heinrich --- %@ 0818677775 --- %D 1994 --- %I IEEE Computer Society --- ]] --- --- local refman = [[ --- TY - JOUR --- T1 - Scientific Visualization, Overviews, Methodologies, and Techniques --- A1 - Nielson, Gregory M --- A1 - Hagen, Hans --- A1 - Müller, Heinrich --- SN - 0818677776 --- Y1 - 1994 --- PB - IEEE Computer Society --- --- TY - JOUR --- T1 - Scientific Visualization, Overviews, Methodologies, and Techniques --- A1 - Nielson, Gregory M --- A1 - Hagen, Hans --- A1 - Müller, Heinrich --- SN - 0818677775 --- Y1 - 1994 --- PB - IEEE Computer Society --- ]] --- --- inspect(publications.endnotes_to_btx(endnote)) --- inspect(publications.refman_to_btx(refman)) diff --git a/tex/context/base/publ-tra.lua b/tex/context/base/publ-tra.lua deleted file mode 100644 index 98c81d800..000000000 --- a/tex/context/base/publ-tra.lua +++ /dev/null @@ -1,296 +0,0 @@ -if not modules then modules = { } end modules ['publ-tra'] = { - version = 1.001, - comment = "this module part of publication support", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local sortedhash = table.sortedhash - -local tracers = { } -publications.tracers = tracers -local datasets = publications.datasets - -local context = context -local NC, NR = context.NC, context.NR -local bold = context.bold -local darkgreen, darkred, darkblue = context.darkgreen, context.darkred, context.darkblue - -local fields = table.sorted { - "abstract", - "address", - "annotate", - "author", - "booktitle", - "chapter", - "comment", - "country", - "doi", - "edition", - "editor", - "eprint", - "howpublished", - "institution", - "isbn", - "issn", - "journal", - "key", - "keyword", - "keywords", - "language", - "lastchecked", - "month", - "names", - "note", - "notes", - "number", - "organization", - "pages", - "publisher", - "school", - "series", - "size", - "title", - "type", - "url", - "volume", - "year", - "nationality", - "assignee", - "bibnumber", - "day", - "dayfiled", - "monthfiled", - "yearfiled", - "revision", -} - -local citevariants = table.sorted { - "author", - "authoryear", - "authoryears", - "authornum", - "year", - "short", - "serial", - "key", - "doi", - "url", - "type", - "page", - "none", - "num", -} - -local listvariants = table.sorted { - "author", - "editor", - "artauthor", -} - --- local categories = table.sorted { --- "article", --- "book", --- "booklet", --- "conference", --- "inbook", --- "incollection", --- "inproceedings", --- "manual", --- "mastersthesis", --- "misc", --- "phdthesis", --- "proceedings", --- "techreport", --- "unpublished", --- } - -local categories = { - article = { - required = { "author", "title", "journal", "year" }, - optional = { "volume", "number", "pages", "month", "note" }, - }, - book = { - required = { { "author", "editor" }, "title", "publisher", "year" }, - optional = { { "volume", "number" }, "series", "address", "edition", "month","note" }, - }, - booklet = { - required = { "title" }, - optional = { "author", "howpublished", "address", "month", "year", "note" }, - }, - inbook = { - required = { { "author", "editor" }, "title", { "chapter", "pages" }, "publisher","year" }, - optional = { { "volume", "number" }, "series", "type", "address", "edition", "month", "note" }, - }, - incollection = { - required = { "author", "title", "booktitle", "publisher", "year" }, - optional = { "editor", { "volume", "number" }, "series", "type", "chapter", "pages", "address", "edition", "month", "note" }, - }, - inproceedings = { - required = { "author", "title", "booktitle", "year" }, - optional = { "editor", { "volume", "number" }, "series", "pages", "address", "month","organization", "publisher", "note" }, - }, - manual = { - required = { "title" }, - optional = { "author", "organization", "address", "edition", "month", "year", "note" }, - }, - mastersthesis = { - required = { "author", "title", "school", "year" }, - optional = { "type", "address", "month", "note" }, - }, - misc = { - required = { "author", "title", "howpublished", "month", "year", "note" }, - optional = { "author", "title", "howpublished", "month", "year", "note" }, - }, - phdthesis = { - required = { "author", "title", "school", "year" }, - optional = { "type", "address", "month", "note" }, - }, - proceedings = { - required = { "title", "year" }, - optional = { "editor", { "volume", "number" }, "series", "address", "month", "organization", "publisher", "note" }, - }, - techreport = { - required = { "author", "title", "institution", "year" }, - optional = { "type", "number", "address", "month", "note" }, - }, - unpublished = { - required = { "author", "title", "note" }, - optional = { "month", "year" }, - }, -} - - -publications.tracers.fields = fields -publications.tracers.categories = categories -publications.tracers.citevariants = citevariants -publications.tracers.listvariants = listvariants --- -- -- - -function tracers.showdatasetfields(dataset) - local luadata = datasets[dataset].luadata - if next(luadata) then - context.starttabulate { "|lT|lT|pT|" } - NC() bold("tag") - NC() bold("category") - NC() bold("fields") - NC() NR() context.FL() -- HL() - for k, v in sortedhash(luadata) do - NC() context(k) - NC() context(v.category) - NC() - for k, v in sortedhash(v) do - if k ~= "details" and k ~= "tag" and k ~= "category" then - context("%s ",k) - end - end - NC() NR() - end - context.stoptabulate() - end -end - -function tracers.showdatasetcompleteness(dataset) - - dataset = datasets[dataset] - - local preamble = { "|lBTw(10em)|p|" } - - local function required(key,value,indirect) - NC() darkgreen(key) - NC() if indirect then - darkblue(value) - elseif value then - context(value) - else - darkred("\\tttf [missing]") - end - NC() NR() - end - - local function optional(key,value,indirect) - NC() context(key) - NC() if indirect then - darkblue(value) - elseif value then - context(value) - end - NC() NR() - end - - local function identified(tag,crossref) - NC() context("tag") - NC() if crossref then - context("\\tttf %s\\hfill\\darkblue => %s",tag,crossref) - else - context("\\tttf %s",tag) - end - NC() NR() - end - - local luadata = datasets[dataset].luadata - - if next(luadata) then - for tag, entry in table.sortedhash(luadata) do - local category = entry.category - local fields = categories[category] - if fields then - context.starttabulate(preamble) - identified(tag,entry.crossref) - context.HL() - local requiredfields = fields.required - local optionalfields = fields.optional - for i=1,#requiredfields do - local r = requiredfields[i] - if type(r) == "table" then - local okay = true - for i=1,#r do - local ri = r[i] - if rawget(entry,ri) then - required(ri,entry[ri]) - okay = true - elseif entry[ri] then - required(ri,entry[ri],true) - okay = true - end - end - if not okay then - required(table.concat(r,"\\letterbar ")) - end - elseif rawget(entry,r) then - required(r,entry[r]) - elseif entry[r] then - required(r,entry[r],true) - else - required(r) - end - end - for i=1,#optionalfields do - local o = optionalfields[i] - if type(o) == "table" then - for i=1,#o do - local oi = o[i] - if rawget(entry,oi) then - optional(oi,entry[oi]) - elseif entry[oi] then - optional(oi,entry[oi],true) - end - end - elseif rawget(entry,o) then - optional(o,entry[o]) - elseif entry[o] then - optional(o,entry[o],true) - end - end - context.stoptabulate() - else - -- error - end - end - end - -end - -commands.showbtxdatasetfields = tracers.showdatasetfields -commands.showbtxdatasetcompleteness = tracers.showdatasetcompleteness diff --git a/tex/context/base/publ-tra.mkiv b/tex/context/base/publ-tra.mkiv deleted file mode 100644 index 49fb6d962..000000000 --- a/tex/context/base/publ-tra.mkiv +++ /dev/null @@ -1,35 +0,0 @@ -%D \module -%D [ file=publ-tra, -%D version=2013.12.24, -%D title=\CONTEXT\ Publication Support, -%D subtitle=Tracing, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -% todo: make this a runtime module -% todo: use the module interface - -\writestatus{loading}{ConTeXt Publication Support / Tracing} - -\registerctxluafile{publ-tra}{1.001} - -\unprotect - -\unexpanded\def\showbtxdatasetfields - {\dosingleempty\publ_dataset_show_fields} - -\def\publ_dataset_show_fields[#1]% - {\ctxcommand{showbtxdatasetfields("\iffirstargument#1\else\currentbtxdataset\fi")}} - -\unexpanded\def\showbtxdatasetcompleteness - {\dosingleempty\publ_dataset_show_completeness} - -\def\publ_dataset_show_completeness[#1]% - {\ctxcommand{showbtxdatasetcompleteness("\iffirstargument#1\else\currentbtxdataset\fi")}} - -\protect \endinput diff --git a/tex/context/base/publ-usr.lua b/tex/context/base/publ-usr.lua deleted file mode 100644 index 6bb93ebee..000000000 --- a/tex/context/base/publ-usr.lua +++ /dev/null @@ -1,91 +0,0 @@ -if not modules then modules = { } end modules ['publ-usr'] = { - version = 1.001, - comment = "this module part of publication support", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- local chardata = characters.data - --- local str = [[ --- \startpublication[k=Berdnikov:TB21-2-129,t=article,a={{Berdnikov},{}},y=2000,n=2257,s=BHHJ00] --- \artauthor[]{Alexander}[A.]{}{Berdnikov} --- \artauthor[]{Hans}[H.]{}{Hagen} --- \artauthor[]{Taco}[T.]{}{Hoekwater} --- \artauthor[]{Bogus{\l}aw}[B.]{}{Jackowski} --- \pubyear{2000} --- \arttitle{{Even more MetaFun with \MP: A request for permission}} --- \journal{TUGboat} --- \issn{0896-3207} --- \volume{21} --- \issue{2} --- \pages{129--130} --- \month{6} --- \stoppublication --- ]] - -local remapped = { - artauthor = "author", - arttitle = "title", -} - -local P, Cs, R, Cc, Carg = lpeg.P, lpeg.Cs, lpeg.R, lpeg.Cc, lpeg.Carg - -local function register(target,key,a,b,c,d,e) - key = remapped[key] or key - if b and d and e then - local s = nil - if b ~= "" and b then - s = s and s .. " " .. b or b - end - if d ~= "" and d then - s = s and s .. " " .. d or d - end - if e ~= "" and e then - s = s and s .. " " .. e or e - end - if a ~= "" and a then - s = s and s .. " " .. a or a - end - local value = target[key] - if s then - if value then - target[key] = value .. " and " .. s - else - target[key] = s - end - else - if not value then - target[key] = s - end - end - else - target[key] = b - end -end - -local leftbrace = P("{") -local rightbrace = P("}") -local leftbracket = P("[") -local rightbracket = P("]") - -local key = P("\\") * Cs(R("az","AZ")^1) * lpeg.patterns.space^0 -local mandate = leftbrace * Cs(lpeg.patterns.balanced) * rightbrace + Cc(false) -local optional = leftbracket * Cs((1-rightbracket)^0) * rightbracket + Cc(false) -local value = optional^-1 * mandate^-1 * optional^-1 * mandate^-2 - -local pattern = ((Carg(1) * key * value) / register + P(1))^0 - -function publications.addtexentry(dataset,settings,content) - settings = utilities.parsers.settings_to_hash(settings) - local data = { - tag = settings.tag or settings.k or "no tag", - category = settings.category or settings.t or "article", - } - lpeg.match(pattern,content,1,data) -- can set tag too - dataset.userdata[data.tag] = data - dataset.luadata[data.tag] = data - publications.markasupdated(dataset) - return data -end diff --git a/tex/context/base/publ-usr.mkiv b/tex/context/base/publ-usr.mkiv deleted file mode 100644 index cb078f424..000000000 --- a/tex/context/base/publ-usr.mkiv +++ /dev/null @@ -1,2 +0,0 @@ -% todo - diff --git a/tex/context/base/publ-xml.mkiv b/tex/context/base/publ-xml.mkiv deleted file mode 100644 index 007f9bb27..000000000 --- a/tex/context/base/publ-xml.mkiv +++ /dev/null @@ -1,114 +0,0 @@ -%D \module -%D [ file=publ-xml, -%D version=2013.12.24, -%D title=\CONTEXT\ Publication Support, -%D subtitle=XML, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Publication Support / XML} - -\unprotect - -\unexpanded\def\convertbtxdatasettoxml - {\dosingleempty\publ_convert_to_xml} - -\def\publ_convert_to_xml[#1]% - {\ctxcommand{convertbtxdatasettoxml("\iffirstargument#1\else\v!standard\fi",true)}} % or current when not empty - -% \startxmlsetups btx:initialize -% \xmlregistereddocumentsetups{#1}{} -% \xmlsetsetup{#1}{bibtex|entry|field}{btx:*} -% \xmlmain{#1} -% \stopxmlsetups - -\startxmlsetups btx:initialize - \xmlsetsetup{#1}{bibtex|entry|field}{btx:*} - \xmlmain{#1} -\stopxmlsetups - -% \startxmlsetups btx:entry -% \xmlflush{#1} -% \stopxmlsetups - -\startxmlsetups btx:field - \xmlflushcontext{#1} -\stopxmlsetups - -\protect \endinput - -% \startxmlsetups bibtex:entry:getkeys -% \xmladdsortentry{bibtex}{#1}{\xmlfilter{#1}{/field[@name='author']/text()}} -% \xmladdsortentry{bibtex}{#1}{\xmlfilter{#1}{/field[@name='year' ]/text()}} -% \xmladdsortentry{bibtex}{#1}{\xmlatt{#1}{tag}} -% \stopxmlsetups - -% \startbuffer -% \startxmlsetups xml:bibtex:sorter -% \xmlresetsorter{bibtex} -% % \xmlfilter{#1}{entry/command(bibtex:entry:getkeys)} -% \xmlfilter{#1}{ -% bibtex -% /entry[@category='article'] -% /field[@name='author' and find(text(),'Knuth')] -% /../command(bibtex:entry:getkeys)} -% \xmlsortentries{bibtex} -% \xmlflushsorter{bibtex}{bibtex:entry:flush} -% \stopxmlsetups -% \stopbuffer - -% \bgroup -% \setups[bibtex-commands] -% \getbuffer -% \egroup - -% \startxmlsetups bibtex:entry:flush -% \xmlfilter{#1}{/field[@name='author']/context()} / % -% \xmlfilter{#1}{/field[@name='year' ]/context()} / % -% \xmlatt{#1}{tag}\par -% \stopxmlsetups - -% \startpacked -% \getbuffer -% \stoppacked - - -% \unexpanded\def\btx_xml_list_handle_entry -% {\begingroup -% \ignorespaces -% \xmlfilter{btx:\currentbtxrendering}{/bibtex/entry[@tag='\currentbtxtag']/command(btx:format)}% -% \removeunwantedspaces -% \endgroup} - -% \startxmlsetups btx:format -% \btxlistparameter\c!before\relax % prevents lookahead -% \edef\currentbibxmlnode {#1} -% \edef\currentbibxmltag {\xmlatt{#1}{tag}} -% \edef\currentbtxcategory{\xmlatt{#1}{category}} -% \ignorespaces -% \xmlcommand{#1}{.}{btx:\currentbtxformat:\currentbibxmlcategory} -% \removeunwantedspaces -% \btxlistparameter\c!after\relax % prevents lookahead -% \stopxmlsetups - -% \startxmlsetups btx:list -% \xmlfilter{#1}{/bibtex/entry/command(bibtex:format)} -% \stopxmlsetups - -% \startxmlsetups btx:btx -% \xmlfilter{#1}{/entry/command(btx:format)} -% \stopxmlsetups - -% \unexpanded\def\btx_xml_doifelse#1{\xmldoifelse\currentbibxmlnode{/field[@name='#1']}} -% \unexpanded\def\btx_xml_doif #1{\xmldoif \currentbibxmlnode{/field[@name='#1']}} -% \unexpanded\def\btx_xml_doifnot #1{\xmldoifnot \currentbibxmlnode{/field[@name='#1']}} -% \def\btx_xml_flush #1{\xmlcontext \currentbibxmlnode{/field[@name='#1']}} -% \def\btx_xml_setup {\xmlsetup \currentbibxmlnode} % {#1} -% \unexpanded\def\btx_xml_todo #1{[#1]} - -% \xmlfilter{#1}{/field[@name='\currentbtxfield']/btxconcat('\currentbtxfield')} diff --git a/tex/context/base/s-abr-01.tex b/tex/context/base/s-abr-01.tex index e9ea6393b..7d8064b29 100644 --- a/tex/context/base/s-abr-01.tex +++ b/tex/context/base/s-abr-01.tex @@ -34,7 +34,6 @@ %logo [FGA] {fga} %logo [FGBBS] {fgbbs} \logo [ACROBAT] {Acro\-bat} -\logo [APA] {apa} \logo [AFM] {afm} \logo [API] {api} \logo [ALEPH] {Aleph} % {\mathematics{\aleph}} @@ -48,7 +47,6 @@ \logo [ASCIITEX] {ascii\TeX} \logo [BACHOTEX] {Bacho\TeX} \logo [BIBTEX] {bib\TeX} -\logo [MLBIBTEX] {MLbib\TeX} \logo [BLUESKY] {BlueSky} \logo [BMP] {bmp} \logo [BSD] {bsd} diff --git a/tex/context/base/s-inf-03.mkiv b/tex/context/base/s-inf-03.mkiv index fc654fef5..822173d00 100644 --- a/tex/context/base/s-inf-03.mkiv +++ b/tex/context/base/s-inf-03.mkiv @@ -16,7 +16,7 @@ \definefont [TitlePageFont] - [MonoBold at 15pt] + [MonoBold at 16pt] \setupbodyfont [tt,8pt] @@ -25,7 +25,7 @@ \definefont [TitlePageFont] - [MonoBold at 18pt] + [MonoBold at 20pt] \setupbodyfont [tt] @@ -352,7 +352,6 @@ for k, v in table.sortedpairs(_G) do end end - \stopluacode \stoptext diff --git a/tex/context/base/s-languages-hyphenation.lua b/tex/context/base/s-languages-hyphenation.lua index c16c5bd2d..660392f80 100644 --- a/tex/context/base/s-languages-hyphenation.lua +++ b/tex/context/base/s-languages-hyphenation.lua @@ -24,7 +24,7 @@ local newglue = nodepool.glue local insert_node_after = node.insert_after local traverse_by_id = node.traverse_id local hyphenate = lang.hyphenate -local find_tail = node.tail +local find_tail = node.slide local remove_node = nodes.remove local tracers = nodes.tracers diff --git a/tex/context/base/s-math-coverage.lua b/tex/context/base/s-math-coverage.lua index 5f1c7cc5a..a74e24450 100644 --- a/tex/context/base/s-math-coverage.lua +++ b/tex/context/base/s-math-coverage.lua @@ -123,7 +123,7 @@ function moduledata.math.coverage.showalphabets() end function moduledata.math.coverage.showcharacters() - context.startmixedcolumns() + context.startcolumns() context.setupalign { "nothyphenated" } context.starttabulate { "|T|i2|Tpl|" } for u, d in table.sortedpairs(chardata) do @@ -150,7 +150,7 @@ function moduledata.math.coverage.showcharacters() end end context.stoptabulate() - context.stopmixedcolumns() + context.stopcolumns() end -- This is a somewhat tricky table as we need to bypass the math machinery. diff --git a/tex/context/base/scrp-cjk.lua b/tex/context/base/scrp-cjk.lua index 9050da6be..681fc4c43 100644 --- a/tex/context/base/scrp-cjk.lua +++ b/tex/context/base/scrp-cjk.lua @@ -14,29 +14,15 @@ if not modules then modules = { } end modules ['scrp-cjk'] = { -- sense either because otherwise a wanted space at the end of a -- line would have to be a hard coded ones. -local utfchar = utf.getchar - -local nuts = nodes.nuts -local tonut = nodes.tonut -local tonode = nodes.tonode - -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before -local copy_node = nuts.copy -local remove_node = nuts.remove -local traverse_id = nuts.traverse_id - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getfont = nuts.getfont -local getchar = nuts.getchar -local getid = nuts.getid -local getattr = nuts.getattr -local getsubtype = nuts.getsubtype -local getfield = nuts.getfield -local setfield = nuts.setfield - -local nodepool = nuts.pool +local utfchar = utf.char + +local insert_node_after = nodes.insert_after +local insert_node_before = nodes.insert_before +local remove_node = nodes.remove +local copy_node = nodes.copy +local traverse_id = nodes.traverse_id + +local nodepool = nodes.pool local new_glue = nodepool.glue local new_kern = nodepool.kern local new_penalty = nodepool.penalty @@ -102,20 +88,20 @@ end -- at font definition time and/or just assume a correct font local function trace_detail(current,what) - local prev = getprev(current) - local c_id = getid(current) - local p_id = prev and getid(prev) + local prev = current.prev + local c_id = current.id + local p_id = prev and prev.id if c_id == glyph_code then - local c_ch = getchar(current) + local c_ch = current.char if p_id == glyph_code then - local p_ch = p_id and getchar(prev) + local p_ch = p_id and prev.char report_details("[%C %a] [%s] [%C %a]",p_ch,hash[p_ch],what,c_ch,hash[c_ch]) else report_details("[%s] [%C %a]",what,c_ch,hash[c_ch]) end else if p_id == glyph_code then - local p_ch = p_id and getchar(prev) + local p_ch = p_id and prev.char report_details("[%C %a] [%s]",p_ch,hash[p_ch],what) else report_details("[%s]",what) @@ -124,8 +110,8 @@ local function trace_detail(current,what) end local function trace_detail_between(p,n,what) - local p_ch = getchar(p) - local n_ch = getchar(n) + local p_ch = p.char + local n_ch = n.char report_details("[%C %a] [%s] [%C %a]",p_ch,hash[p_ch],what,n_ch,hash[n_ch]) end @@ -441,29 +427,29 @@ local function process(head,first,last) if first ~= last then local lastfont, previous, last = nil, "start", nil while true do - local upcoming, id = getnext(first), getid(first) + local upcoming, id = first.next, first.id if id == glyph_code then - local a = getattr(first,a_scriptstatus) + local a = first[a_scriptstatus] local current = numbertocategory[a] local action = injectors[previous] if action then action = action[current] if action then - local font = getfont(first) + local font = first.font if font ~= lastfont then lastfont = font - set_parameters(font,numbertodataset[getattr(first,a_scriptinjection)]) + set_parameters(font,numbertodataset[first[a_scriptinjection]]) end action(head,first) end end previous = current else -- glue - local p, n = getprev(first), upcoming + local p, n = first.prev, upcoming if p and n then - local pid, nid = getid(p), getid(n) + local pid, nid = p.id, n.id if pid == glyph_code and nid == glyph_code then - local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus) + local pa, na = p[a_scriptstatus], n[a_scriptstatus] local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" @@ -509,24 +495,23 @@ scripts.installmethod { } function scripts.decomposehangul(head) - local head = tonut(head) local done = false for current in traverse_id(glyph_code,head) do - local lead_consonant, medial_vowel, tail_consonant = decomposed(getchar(current)) + local lead_consonant, medial_vowel, tail_consonant = decomposed(current.char) if lead_consonant then - setfield(current,"char",lead_consonant) + current.char = lead_consonant local m = copy_node(current) - setfield(m,"char",medial_vowel) + m.char = medial_vowel head, current = insert_node_after(head,current,m) if tail_consonant then local t = copy_node(current) - setfield(t,"char",tail_consonant) + t.char = tail_consonant head, current = insert_node_after(head,current,t) end done = true end end - return tonode(head), done + return head, done end -- nodes.tasks.prependaction("processors","normalizers","scripts.decomposehangul") @@ -697,29 +682,29 @@ local function process(head,first,last) if first ~= last then local lastfont, previous, last = nil, "start", nil while true do - local upcoming, id = getnext(first), getid(first) + local upcoming, id = first.next, first.id if id == glyph_code then - local a = getattr(first,a_scriptstatus) + local a = first[a_scriptstatus] local current = numbertocategory[a] local action = injectors[previous] if action then action = action[current] if action then - local font = getfont(first) + local font = first.font if font ~= lastfont then lastfont = font - set_parameters(font,numbertodataset[getattr(first,a_scriptinjection)]) + set_parameters(font,numbertodataset[first[a_scriptinjection]]) end action(head,first) end end previous = current else -- glue - local p, n = getprev(first), upcoming + local p, n = first.prev, upcoming if p and n then - local pid, nid = getid(p), getid(n) + local pid, nid = p.id, n.id if pid == glyph_code and nid == glyph_code then - local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus) + local pa, na = p[a_scriptstatus], n[a_scriptstatus] local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" @@ -919,32 +904,34 @@ local function process(head,first,last) if first ~= last then local lastfont, previous, last = nil, "start", nil while true do - local upcoming, id = getnext(first), getid(first) + local upcoming, id = first.next, first.id if id == glyph_code then - local a = getattr(first,a_scriptstatus) + local a = first[a_scriptstatus] local current = numbertocategory[a] local action = injectors[previous] if action then action = action[current] if action then - local font = getfont(first) + local font = first.font if font ~= lastfont then lastfont = font - set_parameters(font,numbertodataset[getattr(first,a_scriptinjection)]) + set_parameters(font,numbertodataset[first[a_scriptinjection]]) end action(head,first) end end previous = current - -- elseif id == math_code then - -- upcoming = getnext(end_of_math(current)) - -- previous = "start" + +-- elseif id == math_code then +-- upcoming = end_of_math(current).next +-- previous = "start" + else -- glue - local p, n = getprev(first), upcoming -- we should remember prev + local p, n = first.prev, upcoming -- we should remember prev if p and n then - local pid, nid = getid(p), getid(n) + local pid, nid = p.id, n.id if pid == glyph_code and nid == glyph_code then - local pa, na = getattr(p,a_scriptstatus), getattr(n,a_scriptstatus) + local pa, na = p[a_scriptstatus], n[a_scriptstatus] local pcjk, ncjk = pa and numbertocategory[pa], na and numbertocategory[na] if not pcjk or not ncjk or pcjk == "korean" or ncjk == "korean" @@ -953,17 +940,17 @@ local function process(head,first,last) or pcjk == "half_width_close" or ncjk == "half_width_open" then -- extra compared to korean previous = "start" else -- if head ~= first then - if id == glue_code and getsubtype(first) == userskip_code then -- also scriptstatus check? - -- for the moment no distinction possible between space and userskip - local w = getfield(getfield(first,"spec"),"width") - local s = spacedata[getfont(p)] - if w == s then -- could be option - if trace_details then - trace_detail_between(p,n,"space removed") - end - remove_node(head,first,true) - end - end +if id == glue_code and first.subtype == userskip_code then -- also scriptstatus check? + -- for the moment no distinction possible between space and userskip + local w = first.spec.width + local s = spacedata[p.font] + if w == s then -- could be option + if trace_details then + trace_detail_between(p,n,"space removed") + end + remove_node(head,first,true) + end +end previous = pcjk -- else -- previous = pcjk diff --git a/tex/context/base/scrp-eth.lua b/tex/context/base/scrp-eth.lua index 8ecbce522..597afa1b5 100644 --- a/tex/context/base/scrp-eth.lua +++ b/tex/context/base/scrp-eth.lua @@ -9,17 +9,9 @@ if not modules then modules = { } end modules ['scrp-eth'] = { -- at some point I will review the script code but for the moment we -- do it this way; so space settings like with cjk yet -local nuts = nodes.nuts +local insert_node_before = node.insert_before -local getnext = nuts.getnext -local getfont = nuts.getfont -local getchar = nuts.getchar -local getid = nuts.getid -local getattr = nuts.getattr - -local insert_node_before = nuts.insert_before - -local nodepool = nuts.pool +local nodepool = nodes.pool local new_glue = nodepool.glue local new_penalty = nodepool.penalty @@ -45,13 +37,13 @@ local inter_character_stretch_factor = 1 local inter_character_shrink_factor = 1 local function space_glue(current) - local data = numbertodataset[getattr(current,a_scriptinjection)] + local data = numbertodataset[current[a_scriptinjection]] if data then inter_character_space_factor = data.inter_character_space_factor or 1 inter_character_stretch_factor = data.inter_character_stretch_factor or 1 inter_character_shrink_factor = data.inter_character_shrink_factor or 1 end - local font = getfont(current) + local font = current.font if lastfont ~= font then local pf = parameters[font] space = pf.space @@ -112,9 +104,9 @@ local function process(head,first,last) local injector = false local current = first while current do - local id = getid(current) + local id = current.id if id == glyph_code then - local scriptstatus = getattr(current,a_scriptstatus) + local scriptstatus = current[a_scriptstatus] local category = numbertocategory[scriptstatus] if injector then local action = injector[category] @@ -129,7 +121,7 @@ local function process(head,first,last) if current == last then break else - current = getnext(current) + current = current.next end end end diff --git a/tex/context/base/scrp-ini.lua b/tex/context/base/scrp-ini.lua index a6bfe4cf9..56422e622 100644 --- a/tex/context/base/scrp-ini.lua +++ b/tex/context/base/scrp-ini.lua @@ -14,7 +14,7 @@ local attributes, nodes, node = attributes, nodes, node local trace_analyzing = false trackers.register("scripts.analyzing", function(v) trace_analyzing = v end) local trace_injections = false trackers.register("scripts.injections", function(v) trace_injections = v end) local trace_splitting = false trackers.register("scripts.splitting", function(v) trace_splitting = v end) -local trace_splitdetail = false trackers.register("scripts.splitting.detail", function(v) trace_splitdetail = v end) +local trace_splitdetail = false trackers.register("scripts.splitring.detail", function(v) trace_splitdetail = v end) local report_preprocessing = logs.reporter("scripts","preprocessing") local report_splitting = logs.reporter("scripts","splitting") @@ -22,6 +22,9 @@ local report_splitting = logs.reporter("scripts","splitting") local utfbyte, utfsplit = utf.byte, utf.split local gmatch = string.gmatch +local first_glyph = node.first_glyph or node.first_character +local traverse_id = node.traverse_id + local texsetattribute = tex.setattribute local nodecodes = nodes.nodecodes @@ -45,23 +48,9 @@ local setmetatableindex = table.setmetatableindex local enableaction = nodes.tasks.enableaction local disableaction = nodes.tasks.disableaction -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getchar = nuts.getchar -local getfont = nuts.getfont -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr - -local insert_node_after = nuts.insert_after -local first_glyph = nuts.first_glyph -local traverse_id = nuts.traverse_id - -local nodepool = nuts.pool +local insert_node_after = node.insert_after +local nodepool = nodes.pool local new_glue = nodepool.glue local new_rule = nodepool.rule local new_penalty = nodepool.penalty @@ -411,7 +400,7 @@ scripts.numbertocategory = numbertocategory local function colorize(start,stop) for n in traverse_id(glyph_code,start) do - local kind = numbertocategory[getattr(n,a_scriptstatus)] + local kind = numbertocategory[n[a_scriptstatus]] if kind then local ac = scriptcolors[kind] if ac then @@ -443,17 +432,16 @@ end -- we can have a fonts.hashes.originals function scripts.injectors.handler(head) - head = tonut(head) local start = first_glyph(head) -- we already have glyphs here (subtype 1) if not start then - return tonode(head), false + return head, false else local last_a, normal_process, lastfont, originals = nil, nil, nil, nil local done, first, last, ok = false, nil, nil, false while start do - local id = getid(start) + local id = start.id if id == glyph_code then - local a = getattr(start,a_scriptinjection) + local a = start[a_scriptinjection] if a then if a ~= last_a then if first then @@ -475,7 +463,7 @@ function scripts.injectors.handler(head) normal_process = handler.injector end if normal_process then - local f = getfont(start) + local f = start.font if f ~= lastfont then originals = fontdata[f].resources if resources then @@ -485,13 +473,13 @@ function scripts.injectors.handler(head) end lastfont = f end - local c = getchar(start) + local c = start.char if originals then c = originals[c] or c end local h = hash[c] if h then - setattr(start,a_scriptstatus,categorytonumber[h]) + start[a_scriptstatus] = categorytonumber[h] if not first then first, last = start, start else @@ -552,7 +540,7 @@ function scripts.injectors.handler(head) first, last = nil, nil end end - start = getnext(start) + start = start.next end if ok then if trace_analyzing then @@ -565,7 +553,7 @@ function scripts.injectors.handler(head) end done = true end - return tonode(head), done + return head, done end end @@ -695,11 +683,11 @@ end) local categories = characters.categories or { } local function hit(root,head) - local current = getnext(head) + local current = head.next local lastrun = false local lastfinal = false - while current and getid(current) == glyph_code do - local char = getchar(current) + while current and current.id == glyph_code do + local char = current.char local newroot = root[char] if newroot then local final = newroot.final @@ -713,7 +701,7 @@ local function hit(root,head) else return lastrun, lastfinal end - current = getnext(current) + current = current.next end if lastrun then return lastrun, lastfinal @@ -722,13 +710,12 @@ end local tree, attr, proc -function splitters.handler(head) -- todo: also first_glyph test - head = tonut(head) +function splitters.handler(head) local current = head local done = false while current do - if getid(current) == glyph_code then - local a = getattr(current,a_scriptsplitting) + if current.id == glyph_code then + local a = current[a_scriptsplitting] if a then if a ~= attr then local handler = numbertohandler[a] @@ -737,14 +724,14 @@ function splitters.handler(head) -- todo: also first_glyph test proc = handler.splitter end if proc then - local root = tree[getchar(current)] + local root = tree[current.char] if root then -- we don't check for attributes in the hitter (yet) local last, final = hit(root,current) if last then - local next = getnext(last) - if next and getid(next) == glyph_code then - local nextchar = getchar(next) + local next = last.next + if next and next.id == glyph_code then + local nextchar = next.char if tree[nextchar] then if trace_splitdetail then if type(final) == "string" then @@ -773,9 +760,9 @@ function splitters.handler(head) -- todo: also first_glyph test end end end - current = getnext(current) + current = current.next end - return tonode(head), done + return head, done end local function marker(head,current,font,color) -- could become: nodes.tracers.marker @@ -805,8 +792,8 @@ end local last_a, last_f, last_s, last_q function splitters.insertafter(handler,head,first,last,detail) - local a = getattr(first,a_scriptsplitting) - local f = getfont(first) + local a = first[a_scriptsplitting] + local f = first.font if a ~= last_a or f ~= last_f then last_s = emwidths[f] * numbertodataset[a].inter_word_stretch_factor last_a = a @@ -883,15 +870,15 @@ setmetatableindex(cache_nop,function(t,k) local v = { } t[k] = v return v end) -- playing nice function autofontfeature.handler(head) - for n in traverse_id(glyph_code,tonut(head)) do - -- if getattr(n,a_scriptinjection) then + for n in traverse_id(glyph_code,head) do + -- if n[a_scriptinjection] then -- -- already tagged by script feature, maybe some day adapt -- else - local char = getchar(n) + local char = n.char local script = otfscripts[char] if script then - local dynamic = getattr(n,0) or 0 - local font = getfont(n) + local dynamic = n[0] or 0 + local font = n.font if dynamic > 0 then local slot = cache_yes[font] local attr = slot[script] @@ -917,7 +904,7 @@ function autofontfeature.handler(head) end end if attr ~= 0 then - setattr(n,0,attr) + n[0] = attr -- maybe set scriptinjection when associated end end diff --git a/tex/context/base/sort-ini.lua b/tex/context/base/sort-ini.lua index d279f1253..479d1c489 100644 --- a/tex/context/base/sort-ini.lua +++ b/tex/context/base/sort-ini.lua @@ -82,7 +82,7 @@ local v_first = variables.first local v_last = variables.last local validmethods = table.tohash { - "ch", -- raw character (for tracing) + -- "ch", -- raw character "mm", -- minus mapping "zm", -- zero mapping "pm", -- plus mapping @@ -120,7 +120,7 @@ local sorters = sorters local constants = sorters.constants local data, language, method, digits -local replacements, m_mappings, z_mappings, p_mappings, entries, orders, lower, upper, method, sequence, usedinsequence +local replacements, m_mappings, z_mappings, p_mappings, entries, orders, lower, upper, method, sequence local thefirstofsplit local mte = { -- todo: assign to t @@ -334,9 +334,6 @@ local function setlanguage(l,m,d,u) end end data.sequence = sequence - usedinsequence = table.tohash(sequence) - data.usedinsequence = usedinsequence --- usedinsequence.ch = true -- better just store the string if trace_tests then report_sorters("using sort sequence: % t",sequence) end @@ -375,9 +372,7 @@ local function basicsort(sort_a,sort_b) return 0 end --- todo: compile compare function - -local function basic(a,b) -- trace ea and eb +function comparers.basic(a,b) -- trace ea and eb local ea, eb = a.split, b.split local na, nb = #ea, #eb if na == 0 and nb == 0 then @@ -437,12 +432,6 @@ local function basic(a,b) -- trace ea and eb end end -comparers.basic = basic - -function sorters.basicsorter(a,b) - return basic(a,b) == -1 -end - local function numify(s) s = digitsoffset + tonumber(s) -- alternatively we can create range if s > digitsmaximum then @@ -488,7 +477,7 @@ sorters.firstofsplit = firstofsplit -- for the moment we use an inefficient bunch of tables but once -- we know what combinations make sense we can optimize this -function splitters.utf(str,checked) -- we could append m and u but this is cleaner, s is for tracing +function splitters.utf(str) -- we could append m and u but this is cleaner, s is for tracing if #replacements > 0 then -- todo make an lpeg for this for k=1,#replacements do @@ -591,31 +580,18 @@ function splitters.utf(str,checked) -- we could append m and u but this is clean -- p_mapping = { p_mappings[fs][1] } -- end -- end + local t = { + ch = char, + uc = byte, + mc = m_case, + zc = z_case, + pc = p_case, + mm = m_mapping, + zm = z_mapping, + pm = p_mapping, + } - if checked then - return { - ch = trace_tests and char or nil, -- not in sequence - uc = usedinsequence.uc and byte or nil, - mc = usedinsequence.mc and m_case or nil, - zc = usedinsequence.zc and z_case or nil, - pc = usedinsequence.pc and p_case or nil, - mm = usedinsequence.mm and m_mapping or nil, - zm = usedinsequence.zm and z_mapping or nil, - pm = usedinsequence.pm and p_mapping or nil, - } - else - return { - ch = char, - uc = byte, - mc = m_case, - zc = z_case, - pc = p_case, - mm = m_mapping, - zm = z_mapping, - pm = p_mapping, - } - end - + return t end local function packch(entry) diff --git a/tex/context/base/sort-lan.lua b/tex/context/base/sort-lan.lua index 6b0cc5007..6d16c0d80 100644 --- a/tex/context/base/sort-lan.lua +++ b/tex/context/base/sort-lan.lua @@ -310,7 +310,7 @@ local ch, CH = utfchar(replacementoffset + 1), utfchar(replacementoffset + 11) definitions["cz"] = { replacements = { - { "ch", ch }, { "Ch", ch }, { "CH", ch } + { "ch", ch }, { "CH", CH } }, entries = { ["a"] = "a", ["á"] = "a", ["b"] = "b", ["c"] = "c", ["č"] = "č", diff --git a/tex/context/base/spac-ali.lua b/tex/context/base/spac-ali.lua index 08e33c5b8..25cc6cd66 100644 --- a/tex/context/base/spac-ali.lua +++ b/tex/context/base/spac-ali.lua @@ -10,26 +10,13 @@ local div = math.div local format = string.format local tasks = nodes.tasks +local appendaction = tasks.appendaction +local prependaction = tasks.prependaction +local disableaction = tasks.disableaction local enableaction = tasks.enableaction -local nuts = nodes.nuts -local nodepool = nuts.pool - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr -local setattr = nuts.setattr -local getsubtype = nuts.getsubtype - -local hpack_nodes = nuts.hpack -- nodes.fasthpack not really faster here -local linked_nodes = nuts.linked +local slide_nodes = node.slide +local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here local unsetvalue = attributes.unsetvalue @@ -40,6 +27,8 @@ local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local line_code = listcodes.line +local nodepool = nodes.pool + local new_stretch = nodepool.stretch local a_realign = attributes.private("realign") @@ -67,10 +56,10 @@ local function handler(head,leftpage,realpageno) local current = head local done = false while current do - local id = getid(current) + local id = current.id if id == hlist_code then - if getsubtype(current) == line_code then - local a = getattr(current,a_realign) + if current.subtype == line_code then + local a = current[a_realign] if not a or a == 0 then -- skip else @@ -86,12 +75,12 @@ local function handler(head,leftpage,realpageno) action = leftpage and 2 or 1 end if action == 1 then - setfield(current,"list",hpack_nodes(linked_nodes(getlist(current),new_stretch(3)),getfield(current,"width"),"exactly")) + current.list = hpack_nodes(current.list .. new_stretch(3),current.width,"exactly") if trace_realign then report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno) end elseif action == 2 then - setfield(current,"list",hpack_nodes(linked_nodes(new_stretch(3),getlist(current)),getfield(current,"width"),"exactly")) + current.list = hpack_nodes(new_stretch(3) .. current.list,current.width,"exactly") if trace_realign then report_realign("flushing right. align %a, page %a, realpage %a",align,pageno,realpageno) end @@ -101,14 +90,14 @@ local function handler(head,leftpage,realpageno) done = true nofrealigned = nofrealigned + 1 end - setattr(current,a_realign,unsetvalue) + current[a_realign] = unsetvalue end end - handler(getlist(current),leftpage,realpageno) + handler(current.list,leftpage,realpageno) elseif id == vlist_code then - handler(getlist(current),leftpage,realpageno) + handler(current.list,leftpage,realpageno) end - current = getnext(current) + current = current.next end return head, done end @@ -116,8 +105,7 @@ end function alignments.handler(head) local leftpage = isleftpage(true,false) local realpageno = texgetcount("realpageno") - local head, done = handler(tonut(head),leftpage,realpageno) - return tonode(head), done + return handler(head,leftpage,realpageno) end local enabled = false diff --git a/tex/context/base/spac-ali.mkiv b/tex/context/base/spac-ali.mkiv index cf95064a2..9c7e81379 100644 --- a/tex/context/base/spac-ali.mkiv +++ b/tex/context/base/spac-ali.mkiv @@ -585,36 +585,13 @@ \unexpanded\def\spac_align_use_now#1% {\csname\??alignmentnormalcache#1\endcsname} -% Maybe we need something different in columns. +% The keywords: \unexpanded\def\installalign#1#2% beware: commands must be unexpandable! {\ifcsname\??aligncommand#1\endcsname \else \setvalue{\??aligncommand#1}{\t_spac_align_collected\expandafter{\the\t_spac_align_collected#2}}% \fi} -% beware, toks stuff and states are set at a differt time, so installalign is -% only for special options -% -% \setvalue{\??aligncommand whatever}% -% {\c_spac_align_state_horizontal\plushundred -% \t_spac_align_collected\expandafter{\the\t_spac_align_collected .....}} -% -% this one could deal with both -% -% \unexpanded\def\installalignoption#1#2% -% {\ifcsname\??aligncommand#1\endcsname \else -% \setvalue{\??aligncommand#1}% -% {\spac_align_set_horizontal_none -% \c_spac_align_state_horizontal\plushundred % don't set -% \t_spac_align_collected\expandafter{\the\t_spac_align_collected#2}}% -% \fi} -% -% \installalignoption -% {whatever} -% {} - -% The keywords: - \letvalue{\??aligncommand\empty }\empty \setvalue{\??aligncommand\v!broad }{\c_spac_align_state_broad \plusone } \setvalue{\??aligncommand\v!wide }{\c_spac_align_state_broad \plustwo } diff --git a/tex/context/base/spac-chr.lua b/tex/context/base/spac-chr.lua index 4122a64b6..db98b42a6 100644 --- a/tex/context/base/spac-chr.lua +++ b/tex/context/base/spac-chr.lua @@ -22,29 +22,14 @@ report_characters = logs.reporter("typesetting","characters") local nodes, node = nodes, node -local nuts = nodes.nuts - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -local getfont = nuts.getfont -local getchar = nuts.getchar - -local insert_node_after = nuts.insert_after -local remove_node = nuts.remove -local copy_node_list = nuts.copy_list -local traverse_id = nuts.traverse_id +local insert_node_after = nodes.insert_after +local remove_node = nodes.remove +local copy_node_list = nodes.copy_list +local traverse_id = nodes.traverse_id local tasks = nodes.tasks -local nodepool = nuts.pool +local nodepool = nodes.pool local new_penalty = nodepool.penalty local new_glue = nodepool.glue @@ -78,47 +63,48 @@ local c_zero = byte('0') local c_period = byte('.') local function inject_quad_space(unicode,head,current,fraction) - local attr = getfield(current,"attr") + local attr = current.attr if fraction ~= 0 then - fraction = fraction * fontquads[getfont(current)] + fraction = fraction * fontquads[current.font] end local glue = new_glue(fraction) - setfield(glue,"attr",attr) - setfield(current,"attr",nil) - setattr(glue,a_character,unicode) +-- glue.attr = copy_node_list(attr) + glue.attr = attr + current.attr = nil + glue[a_character] = unicode head, current = insert_node_after(head,current,glue) return head, current end local function inject_char_space(unicode,head,current,parent) - local attr = getfield(current,"attr") - local font = getfont(current) + local attr = current.attr + local font = current.font local char = fontcharacters[font][parent] local glue = new_glue(char and char.width or fontparameters[font].space) - setfield(glue,"attr",attr) - setfield(current,"attr",nil) - setattr(glue,a_character,unicode) + glue.attr = current.attr + current.attr = nil + glue[a_character] = unicode head, current = insert_node_after(head,current,glue) return head, current end local function inject_nobreak_space(unicode,head,current,space,spacestretch,spaceshrink) - local attr = getfield(current,"attr") + local attr = current.attr local glue = new_glue(space,spacestretch,spaceshrink) local penalty = new_penalty(10000) - setfield(glue,"attr",attr) - setfield(current,"attr",nil) - setattr(glue,a_character,unicode) + glue.attr = attr + current.attr = nil + glue[a_character] = unicode head, current = insert_node_after(head,current,penalty) head, current = insert_node_after(head,current,glue) return head, current end local function nbsp(head,current) - local para = fontparameters[getfont(current)] - if getattr(current,a_alignstate) == 1 then -- flushright + local para = fontparameters[current.font] + if current[a_alignstate] == 1 then -- flushright head, current = inject_nobreak_space(0x00A0,head,current,para.space,0,0) - setfield(current,"subtype",space_skip_code) + current.subtype = space_skip_code else head, current = inject_nobreak_space(0x00A0,head,current,para.space,para.spacestretch,para.spaceshrink) end @@ -135,7 +121,7 @@ end function characters.replacenbspaces(head) for current in traverse_id(glyph_code,head) do - if getchar(current) == 0x00A0 then + if current.char == 0x00A0 then local h = nbsp(head,current) if h then head = remove_node(h,current,true) @@ -161,21 +147,21 @@ local methods = { -- don't have the 'local' value. [0x00A0] = function(head,current) -- nbsp - local next = getnext(current) - if next and getid(next) == glyph_code then - local char = getchar(next) + local next = current.next + if next and next.id == glyph_code then + local char = next.char if char == 0x200C or char == 0x200D then -- nzwj zwj - next = getnext(next) - if next and nbsphash[getchar(next)] then + next = next.next + if next and nbsphash[next.char] then return false end elseif nbsphash[char] then return false end end - local prev = getprev(current) - if prev and getid(prev) == glyph_code and nbsphash[getchar(prev)] then - return false + local prev = current.prev + if prev and prev.id == glyph_code and nbsphash[prev.char] then + return false -- kannada end return nbsp(head,current) end, @@ -229,11 +215,11 @@ local methods = { end, [0x202F] = function(head,current) -- narrownobreakspace - return inject_nobreak_space(0x202F,head,current,fontquads[getfont(current)]/8) + return inject_nobreak_space(0x202F,head,current,fontquads[current.font]/8) end, [0x205F] = function(head,current) -- math thinspace - return inject_nobreak_space(0x205F,head,current,fontparameters[getfont(current)].space/8) + return inject_nobreak_space(0x205F,head,current,fontparameters[current.font].space/8) end, -- [0xFEFF] = function(head,current) -- zerowidthnobreakspace @@ -242,15 +228,14 @@ local methods = { } -function characters.handler(head) -- todo: use traverse_id - head = tonut(head) +function characters.handler(head) local current = head local done = false while current do - local id = getid(current) + local id = current.id if id == glyph_code then - local next = getnext(current) - local char = getchar(current) + local next = current.next + local char = current.char local method = methods[char] if method then if trace_characters then @@ -264,8 +249,8 @@ function characters.handler(head) -- todo: use traverse_id end current = next else - current = getnext(current) + current = current.next end end - return tonode(head), done + return head, done end diff --git a/tex/context/base/spac-ver.lua b/tex/context/base/spac-ver.lua index 7d78d6c12..0035c4119 100644 --- a/tex/context/base/spac-ver.lua +++ b/tex/context/base/spac-ver.lua @@ -37,6 +37,7 @@ local nodes, node, trackers, attributes, context, commands, tex = nodes, node, local texlists = tex.lists local texgetdimen = tex.getdimen local texnest = tex.nest +local texgetbox = tex.getbox local variables = interfaces.variables @@ -62,41 +63,23 @@ local a_skiporder = attributes.private('skiporder') local a_snapmethod = attributes.private('snapmethod') local a_snapvbox = attributes.private('snapvbox') -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut -local ntostring = nuts.tostring - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr -local setattr = nuts.setattr -local getsubtype = nuts.getsubtype -local getbox = nuts.getbox - -local find_node_tail = nuts.tail -local free_node = nuts.free -local free_node_list = nuts.flush_list -local copy_node = nuts.copy -local traverse_nodes = nuts.traverse -local traverse_nodes_id = nuts.traverse_id -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local remove_node = nuts.remove -local count_nodes = nuts.count -local hpack_node = nuts.hpack -local vpack_node = nuts.vpack -local writable_spec = nuts.writable_spec -local nodereference = nuts.reference - -local listtoutf = nodes.listtoutf +local find_node_tail = node.tail +local free_node = node.free +local free_node_list = node.flush_list +local copy_node = node.copy +local traverse_nodes = node.traverse +local traverse_nodes_id = node.traverse_id +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local remove_node = nodes.remove +local count_nodes = nodes.count local nodeidstostring = nodes.idstostring +local hpack_node = node.hpack +local vpack_node = node.vpack +local writable_spec = nodes.writable_spec +local listtoutf = nodes.listtoutf -local nodepool = nuts.pool +local nodepool = nodes.pool local new_penalty = nodepool.penalty local new_kern = nodepool.kern @@ -196,26 +179,28 @@ end -- local rule_id = nodecodes.rule -- local vlist_id = nodecodes.vlist -- function nodes.makevtop(n) --- if getid(n) == vlist_id then --- local list = getlist(n) --- local height = (list and getid(list) <= rule_id and getfield(list,"height")) or 0 --- setfield(n,"depth",getfield(n,"depth") - height + getfield(n,"height") --- setfield(n,"height",height +-- if n.id == vlist_id then +-- local list = n.list +-- local height = (list and list.id <= rule_id and list.height) or 0 +-- n.depth = n.depth - height + n.height +-- n.height = height -- end -- end +local reference = nodes.reference + local function validvbox(parentid,list) if parentid == hlist_code then - local id = getid(list) + local id = list.id if id == whatsit_code then -- check for initial par subtype - list = getnext(list) + list = list.next if not next then return nil end end local done = nil for n in traverse_nodes(list) do - local id = getid(n) + local id = n.id if id == vlist_code or id == hlist_code then if done then return nil @@ -229,9 +214,9 @@ local function validvbox(parentid,list) end end if done then - local id = getid(done) + local id = done.id if id == hlist_code then - return validvbox(id,getlist(done)) + return validvbox(id,done.list) end end return done -- only one vbox @@ -241,19 +226,19 @@ end local function already_done(parentid,list,a_snapmethod) -- todo: done when only boxes and all snapped -- problem: any snapped vbox ends up in a line if list and parentid == hlist_code then - local id = getid(list) + local id = list.id if id == whatsit_code then -- check for initial par subtype - list = getnext(list) + list = list.next if not next then return false end end --~ local i = 0 for n in traverse_nodes(list) do - local id = getid(n) ---~ i = i + 1 print(i,nodecodes[id],getattr(n,a_snapmethod)) + local id = n.id +--~ i = i + 1 print(i,nodecodes[id],n[a_snapmethod]) if id == hlist_code or id == vlist_code then - local a = getattr(n,a_snapmethod) + local a = n[a_snapmethod] if not a then -- return true -- not snapped at all elseif a == 0 then @@ -291,11 +276,11 @@ end -- check variables.none etc local function snap_hlist(where,current,method,height,depth) -- method.strut is default - local list = getlist(current) + local list = current.list local t = trace_vsnapping and { } if t then t[#t+1] = formatters["list content: %s"](listtoutf(list)) - t[#t+1] = formatters["parent id: %s"](nodereference(current)) + t[#t+1] = formatters["parent id: %s"](reference(current)) t[#t+1] = formatters["snap method: %s"](method.name) t[#t+1] = formatters["specification: %s"](method.specification) end @@ -327,8 +312,7 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is t[#t+1] = formatters["auto: snapht %p snapdp %p"](snapht,snapdp) end end - local h = height or getfield(current,"height") - local d = depth or getfield(current,"depth") + local h, d = height or current.height, depth or current.depth local hr, dr, ch, cd = method.hfraction or 1, method.dfraction or 1, h, d local tlines, blines = method.tlines or 1, method.blines or 1 local done, plusht, plusdp = false, snapht, snapdp @@ -355,22 +339,22 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is if method.first then local thebox = current - local id = getid(thebox) + local id = thebox.id if id == hlist_code then - thebox = validvbox(id,getlist(thebox)) - id = thebox and getid(thebox) + thebox = validvbox(id,thebox.list) + id = thebox and thebox.id end if thebox and id == vlist_code then - local list = getlist(thebox) + local list = thebox.list local lh, ld for n in traverse_nodes_id(hlist_code,list) do - lh = getfield(n,"height") - ld = getfield(n,"depth") + lh = n.height + ld = n.depth break end if lh then - local ht = getfield(thebox,"height") - local dp = getfield(thebox,"depth") + local ht = thebox.height + local dp = thebox.depth if t then t[#t+1] = formatters["first line: height %p depth %p"](lh,ld) t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) @@ -378,9 +362,9 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is local delta = h - lh ch, cd = lh, delta + d h, d = ch, cd - local shifted = hpack_node(getlist(current)) - setfield(shifted,"shift",delta) - setfield(current,"list",shifted) + local shifted = hpack_node(current.list) + shifted.shift = delta + current.list = shifted done = true if t then t[#t+1] = formatters["first: height %p depth %p shift %p"](ch,cd,delta) @@ -393,21 +377,20 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is end elseif method.last then local thebox = current - local id = getid(thebox) + local id = thebox.id if id == hlist_code then - thebox = validvbox(id,getlist(thebox)) - id = thebox and getid(thebox) + thebox = validvbox(id,thebox.list) + id = thebox and thebox.id end if thebox and id == vlist_code then - local list = getlist(thebox) - local lh, ld + local list, lh, ld = thebox.list for n in traverse_nodes_id(hlist_code,list) do - lh = getfield(n,"height") - ld = getfield(n,"depth") + lh = n.height + ld = n.depth end if lh then - local ht = getfield(thebox,"height") - local dp = getfield(thebox,"depth") + local ht = thebox.height + local dp = thebox.depth if t then t[#t+1] = formatters["last line: height %p depth %p" ](lh,ld) t[#t+1] = formatters["dimensions: height %p depth %p"](ht,dp) @@ -415,9 +398,9 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is local delta = d - ld cd, ch = ld, delta + h h, d = ch, cd - local shifted = hpack_node(getlist(current)) - setfield(shifted,"shift",delta) - setfield(current,"list",shifted) + local shifted = hpack_node(current.list) + shifted.shift = delta + current.list = shifted done = true if t then t[#t+1] = formatters["last: height %p depth %p shift %p"](ch,cd,delta) @@ -478,25 +461,25 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is if offset then -- we need to set the attr if t then - t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width"),getfield(current,"height"),getfield(current,"depth")) + t[#t+1] = formatters["before offset: %p (width %p height %p depth %p)"](offset,current.width,current.height,current.depth) end - local shifted = hpack_node(getlist(current)) - setfield(shifted,"shift",offset) - setfield(current,"list",shifted) + local shifted = hpack_node(current.list) + shifted.shift = offset + current.list = shifted if t then - t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,getfield(current,"width"),getfield(current,"height"),getfield(current,"depth")) + t[#t+1] = formatters["after offset: %p (width %p height %p depth %p)"](offset,current.width,current.height,current.depth) end - setattr(shifted,a_snapmethod,0) - setattr(current,a_snapmethod,0) + shifted[a_snapmethod] = 0 + current[a_snapmethod] = 0 end if not height then - setfield(current,"height",ch) + current.height = ch if t then t[#t+1] = formatters["forced height: %p"](ch) end end if not depth then - setfield(current,"depth",cd) + current.depth = cd if t then t[#t+1] = formatters["forced depth: %p"](cd) end @@ -510,17 +493,17 @@ local function snap_hlist(where,current,method,height,depth) -- method.strut is t[#t+1] = formatters["final depth: %p -> %p"](d,cd) end if t then - report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[getid(current)],t) + report_snapper("trace: %s type %s\n\t%\n\tt",where,nodecodes[current.id],t) end return h, d, ch, cd, lines end local function snap_topskip(current,method) - local spec = getfield(current,"spec") - local w = getfield(spec,"width") + local spec = current.spec + local w = spec.width local wd = w - if getfield(spec,"writable") then - setfield(spec,"width",0) + if spec.writable then + spec.width = 0 wd = 0 end return w, wd @@ -681,18 +664,18 @@ local trace_list, tracing_info, before, after = { }, false, "", "" local function nodes_to_string(head) local current, t = head, { } while current do - local id = getid(current) + local id = current.id local ty = nodecodes[id] if id == penalty_code then - t[#t+1] = formatters["%s:%s"](ty,getfield(current,"penalty")) + t[#t+1] = formatters["%s:%s"](ty,current.penalty) elseif id == glue_code then -- or id == kern_code then -- to be tested t[#t+1] = formatters["%s:%p"](ty,current) elseif id == kern_code then - t[#t+1] = formatters["%s:%p"](ty,getfield(current,"kern")) + t[#t+1] = formatters["%s:%p"](ty,current.kern) else t[#t+1] = ty end - current = getnext(current) + current = current.next end return concat(t," + ") end @@ -716,7 +699,7 @@ local function trace_info(message, where, what) end local function trace_node(what) - local nt = nodecodes[getid(what)] + local nt = nodecodes[what.id] local tl = trace_list[#trace_list] if tl and tl[1] == "node" then trace_list[#trace_list] = { "node", formatters["%s + %s"](tl[2],nt) } @@ -726,8 +709,8 @@ local function trace_node(what) end local function trace_done(str,data) - if getid(data) == penalty_code then - trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,getfield(data,"penalty")) } + if data.id == penalty_code then + trace_list[#trace_list+1] = { "penalty", formatters["%s | %s"](str,data.penalty) } else trace_list[#trace_list+1] = { "glue", formatters["%s | %p"](str,data) } end @@ -765,31 +748,22 @@ local belowdisplayshortskip_code = skipcodes.belowdisplayshortskip local topskip_code = skipcodes.topskip local splittopskip_code = skipcodes.splittopskip --- local function free_glue_node(n) --- free_node(n) --- local s = getfield(n,"spec") --- if s then --- free_node(s) --- end --- end - local free_glue_node = free_node -local free_glue_spec = function() end -- free_node function vspacing.snapbox(n,how) local sv = snapmethods[how] if sv then - local box = getbox(n) - local list = getlist(box) + local box = texgetbox(n) + local list = box.list if list then - local s = getattr(list,a_snapmethod) + local s = list[a_snapmethod] if s == 0 then if trace_vsnapping then -- report_snapper("box list not snapped, already done") end else - local ht = getfield(box,"height") - local dp = getfield(box,"depth") + local ht = box.height + local dp = box.depth if false then -- todo: already_done -- assume that the box is already snapped if trace_vsnapping then @@ -798,14 +772,14 @@ function vspacing.snapbox(n,how) end else local h, d, ch, cd, lines = snap_hlist("box",box,sv,ht,dp) - setfield(box,"height",ch) - setfield(box,"depth",cd) + box.height= ch + box.depth = cd if trace_vsnapping then report_snapper("box list snapped from (%p,%p) to (%p,%p) using method %a (%s) for %a (%s lines): %s", h,d,ch,cd,sv.name,sv.specification,"direct",lines,listtoutf(list)) end - setattr(box,a_snapmethod,0) -- - setattr(list,a_snapmethod,0) -- yes or no + box[a_snapmethod] = 0 -- + list[a_snapmethod] = 0 -- yes or no end end end @@ -827,10 +801,8 @@ local w, h, d = 0, 0, 0 ----- w, h, d = 100*65536, 65536, 65536 local function forced_skip(head,current,width,where,trace) - if head == current then - if getsubtype(head) == baselineskip_code then - width = width - getfield(getfield(head,"spec"),"width") - end + if head == current and head.subtype == baselineskip_code then + width = width - head.spec.width end if width == 0 then -- do nothing @@ -862,25 +834,25 @@ local special_penalty_max = 35000 local function specialpenalty(start,penalty) -- nodes.showsimplelist(texlists.page_head,1) - local current = find_node_tail(tonut(texlists.page_head)) -- no texlists.page_tail yet + local current = find_node_tail(texlists.page_head) while current do - local id = getid(current) + local id = current.id if id == glue_code then - current = getprev(current) + current = current.prev elseif id == penalty_code then - local p = getfield(current,"penalty") + local p = current.penalty if p == penalty then if trace_vspacing then report_vspacing("overloading penalty %a",p) end return current elseif p >= 10000 then - current = getprev(current) + current = current.prev else break end else - current = getprev(current) + current = current.prev end end end @@ -903,12 +875,12 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also head = insert_node_before(head,current,p) end if glue_data then - local spec = getfield(glue_data,"spec") + local spec = glue_data.spec if force_glue then if trace then trace_done("flushed due to " .. why,glue_data) end - head = forced_skip(head,current,getfield(spec,"width"),"before",trace) + head = forced_skip(head,current,spec.width,"before",trace) free_glue_node(glue_data) - elseif getfield(spec,"writable") then + elseif spec.writable then if trace then trace_done("flushed due to " .. why,glue_data) end head = insert_node_before(head,current,glue_data) else @@ -928,12 +900,12 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also end if trace then trace_info("start analyzing",where,what) end while current do - local id = getid(current) + local id = current.id if id == hlist_code or id == vlist_code then -- needs checking, why so many calls if snap then - local list = getlist(current) - local s = getattr(current,a_snapmethod) + local list = current.list + local s = current[a_snapmethod] if not s then -- if trace_vsnapping then -- report_snapper("mvl list not snapped") @@ -947,8 +919,8 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also if sv then -- check if already snapped if list and already_done(id,list,a_snapmethod) then - local ht = getfield(current,"height") - local dp = getfield(current,"depth") + local ht = current.height + local dp = current.depth -- assume that the box is already snapped if trace_vsnapping then report_snapper("mvl list already snapped at (%p,%p): %s",ht,dp,listtoutf(list)) @@ -963,39 +935,40 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also elseif trace_vsnapping then report_snapper("mvl %a not snapped due to unknown snap specification: %s",nodecodes[id],listtoutf(list)) end - setattr(current,a_snapmethod,0) + current[a_snapmethod] = 0 end else -- end -- tex.prevdepth = 0 flush("list") - current = getnext(current) + current = current.next elseif id == penalty_code then - -- natural_penalty = getfield(current,"penalty") + -- natural_penalty = current.penalty -- if trace then trace_done("removed penalty",current) end -- head, current = remove_node(head, current, true) - current = getnext(current) + current = current.next elseif id == kern_code then - if snap and trace_vsnapping and getfield(current,"kern") ~= 0 then - report_snapper("kern of %p kept",getfield(current,"kern")) + if snap and trace_vsnapping and current.kern ~= 0 then + report_snapper("kern of %p kept",current.kern) end flush("kern") - current = getnext(current) + current = current.next elseif id == glue_code then - local subtype = getsubtype(current) + local subtype = current.subtype if subtype == userskip_code then - local sc = getattr(current,a_skipcategory) -- has no default, no unset (yet) - local so = getattr(current,a_skiporder) or 1 -- has 1 default, no unset (yet) - local sp = getattr(current,a_skippenalty) -- has no default, no unset (yet) + local sc = current[a_skipcategory] -- has no default, no unset (yet) + local so = current[a_skiporder] or 1 -- has 1 default, no unset (yet) + local sp = current[a_skippenalty] -- has no default, no unset (yet) if sp and sc == penalty then - if where == "page" and sp >= special_penalty_min and sp <= special_penalty_max then - local previousspecial = specialpenalty(current,sp) - if previousspecial then - setfield(previousspecial,"penalty",0) - sp = 0 - end - end + +if where == "page" and sp >= special_penalty_min and sp <= special_penalty_max then + local previousspecial = specialpenalty(current,sp) + if previousspecial then + previousspecial.penalty = 0 + sp = 0 + end +end if not penalty_data then penalty_data = sp elseif penalty_order < so then @@ -1010,38 +983,37 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also if trace then trace_done("flush",glue_data) end head = insert_node_before(head,current,glue_data) if trace then trace_natural("natural",current) end - current = getnext(current) + current = current.next else -- not look back across head -- todo: prev can be whatsit (latelua) - local previous = getprev(current) - if previous and getid(previous) == glue_code and getsubtype(previous) == userskip_code then - local ps = getfield(previous,"spec") - if getfield(ps,"writable") then - local cs = getfield(current,"spec") - if getfield(cs,"writable") and getfield(ps,"stretch_order") == 0 and getfield(ps,"shrink_order") == 0 and getfield(cs,"stretch_order") == 0 and getfield(cs,"shrink_order") == 0 then - local pw, pp, pm = getfield(ps,"width"), getfield(ps,"stretch"), getfield(ps,"shrink") - local cw, cp, cm = getfield(cs,"width"), getfield(cs,"stretch"), getfield(cs,"shrink") + local previous = current.prev + if previous and previous.id == glue_code and previous.subtype == userskip_code then + local ps = previous.spec + if ps.writable then + local cs = current.spec + if cs.writable and ps.stretch_order == 0 and ps.shrink_order == 0 and cs.stretch_order == 0 and cs.shrink_order == 0 then + local pw, pp, pm = ps.width, ps.stretch, ps.shrink + local cw, cp, cm = cs.width, cs.stretch, cs.shrink -- ps = writable_spec(previous) -- no writable needed here -- ps.width, ps.stretch, ps.shrink = pw + cw, pp + cp, pm + cm - free_glue_spec(ps) - setfield(previous,"spec",new_gluespec(pw + cw, pp + cp, pm + cm)) -- else topskip can disappear + previous.spec = new_gluespec(pw + cw, pp + cp, pm + cm) -- else topskip can disappear if trace then trace_natural("removed",current) end head, current = remove_node(head, current, true) -- current = previous if trace then trace_natural("collapsed",previous) end - -- current = getnext(current) + -- current = current.next else if trace then trace_natural("filler",current) end - current = getnext(current) + current = current.next end else if trace then trace_natural("natural (no prev spec)",current) end - current = getnext(current) + current = current.next end else if trace then trace_natural("natural (no prev)",current) end - current = getnext(current) + current = current.next end end glue_order, glue_data = 0, nil @@ -1074,12 +1046,12 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also elseif glue_order == so then -- is now exclusive, maybe support goback as combi, else why a set if sc == largest then - local cs, gs = getfield(current,"spec"), getfield(glue_data,"spec") - local cw, gw = getfield(cs,"width"), getfield(gs,"width") + local cs, gs = current.spec, glue_data.spec + local cw, gw = cs.width, gs.width if cw > gw then if trace then trace_skip("largest",sc,so,sp,current) end free_glue_node(glue_data) -- also free spec - head, current, glue_data = remove_node(head,current) + head, current, glue_data = remove_node(head, current) else if trace then trace_skip("remove smallest",sc,so,sp,current) end head, current = remove_node(head, current, true) @@ -1087,7 +1059,7 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also elseif sc == goback then if trace then trace_skip("goback",sc,so,sp,current) end free_glue_node(glue_data) -- also free spec - head, current, glue_data = remove_node(head,current) + head, current, glue_data = remove_node(head, current) elseif sc == force then -- last one counts, some day we can provide an accumulator and largest etc -- but not now @@ -1101,11 +1073,11 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also head, current = remove_node(head, current, true) elseif sc == add then if trace then trace_skip("add",sc,so,sp,current) end - -- local old, new = glue_data.spec, getfield(current,"spec") - local old, new = writable_spec(glue_data), getfield(current,"spec") - setfield(old,"width",getfield(old,"width") + getfield(new,"width")) - setfield(old,"stretch",getfield(old,"stretch") + getfield(new,"stretch")) - setfield(old,"shrink",getfield(old,"shrink") + getfield(new,"shrink")) + -- local old, new = glue_data.spec, current.spec + local old, new = writable_spec(glue_data), current.spec + old.width = old.width + new.width + old.stretch = old.stretch + new.stretch + old.shrink = old.shrink + new.shrink -- toto: order head, current = remove_node(head, current, true) else @@ -1121,13 +1093,12 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also end elseif subtype == lineskip_code then if snap then - local s = getattr(current,a_snapmethod) + local s = current[a_snapmethod] if s and s ~= 0 then - setattr(current,a_snapmethod,0) - local spec = getfield(current,"spec") - if getfield(spec,"writable") then + current[a_snapmethod] = 0 + if current.spec.writable then local spec = writable_spec(current) - setfield(spec,"width",0) + spec.width = 0 if trace_vsnapping then report_snapper("lineskip set to zero") end @@ -1140,16 +1111,15 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also if trace then trace_skip("lineskip",sc,so,sp,current) end flush("lineskip") end - current = getnext(current) + current = current.next elseif subtype == baselineskip_code then if snap then - local s = getattr(current,a_snapmethod) + local s = current[a_snapmethod] if s and s ~= 0 then - setattr(current,a_snapmethod,0) - local spec = getfield(current,"spec") - if getfield(spec,"writable") then + current[a_snapmethod] = 0 + if current.spec.writable then local spec = writable_spec(current) - setfield(spec,"width",0) + spec.width = 0 if trace_vsnapping then report_snapper("baselineskip set to zero") end @@ -1162,17 +1132,17 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also if trace then trace_skip("baselineskip",sc,so,sp,current) end flush("baselineskip") end - current = getnext(current) + current = current.next elseif subtype == parskip_code then -- parskip always comes later if ignore_whitespace then if trace then trace_natural("ignored parskip",current) end head, current = remove_node(head, current, true) elseif glue_data then - local ps = getfield(current,"spec") - local gs = getfield(glue_data,"spec") - if getfield(ps,"writable") and getfield(gs,"writable") and getfield(ps,"width") > getfield(gs,"width") then - setfield(glue_data,"spec",copy_node(ps)) + local ps = current.spec + local gs = glue_data.spec + if ps.writable and gs.writable and ps.width > gs.width then + glue_data.spec = copy_node(ps) if trace then trace_natural("taking parskip",current) end else if trace then trace_natural("removed parskip",current) end @@ -1184,9 +1154,9 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also end elseif subtype == topskip_code or subtype == splittopskip_code then if snap then - local s = getattr(current,a_snapmethod) + local s = current[a_snapmethod] if s and s ~= 0 then - setattr(current,a_snapmethod,0) + current[a_snapmethod] = 0 local sv = snapmethods[s] local w, cw = snap_topskip(current,sv) if trace_vsnapping then @@ -1200,46 +1170,46 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also if trace then trace_skip("topskip",sc,so,sp,current) end flush("topskip") end - current = getnext(current) + current = current.next elseif subtype == abovedisplayskip_code then -- if trace then trace_skip("above display skip (normal)",sc,so,sp,current) end flush("above display skip (normal)") - current = getnext(current) + current = current.next -- elseif subtype == belowdisplayskip_code then -- if trace then trace_skip("below display skip (normal)",sc,so,sp,current) end flush("below display skip (normal)") - current = getnext(current) - -- + current = current.next + -- elseif subtype == abovedisplayshortskip_code then -- if trace then trace_skip("above display skip (short)",sc,so,sp,current) end flush("above display skip (short)") - current = getnext(current) + current = current.next -- elseif subtype == belowdisplayshortskip_code then -- if trace then trace_skip("below display skip (short)",sc,so,sp,current) end flush("below display skip (short)") - current = getnext(current) + current = current.next -- else -- other glue if snap and trace_vsnapping then - local spec = getfield(current,"spec") - if getfield(spec,"writable") and getfield(spec,"width") ~= 0 then - report_snapper("glue %p of type %a kept",getfield(spec,"width"),skipcodes[subtype]) - -- setfield(spec,"width",0) + local spec = current.spec + if spec.writable and spec.width ~= 0 then + report_snapper("glue %p of type %a kept",current.spec.width,skipcodes[subtype]) + -- spec.width = 0 end end - if trace then trace_skip(formatters["glue of type %a"](subtype),sc,so,sp,current) end + if trace then trace_skip(formatter["glue of type %a"](subtype),sc,so,sp,current) end flush("some glue") - current = getnext(current) + current = current.next end else - flush(formatters["node with id %a"](id)) - current = getnext(current) + flush("something else") + current = current.next end end if trace then trace_info("stop analyzing",where,what) end @@ -1260,8 +1230,7 @@ local function collapser(head,where,what,trace,snap,a_snapmethod) -- maybe also if not tail then tail = find_node_tail(head) end if trace then trace_done("result",glue_data) end if force_glue then - local spec = getfield(glue_data,"spec") - head, tail = forced_skip(head,tail,getfield(spec,"width"),"after",trace) + head, tail = forced_skip(head,tail,glue_data.spec.width,"after",trace) free_glue_node(glue_data) else head, tail = insert_node_after(head,tail,glue_data) @@ -1274,7 +1243,7 @@ texnest[texnest.ptr].prevdepth = 0 -- appending to the list bypasses tex's prevd end show_tracing(head) if oldhead ~= head then - trace_info("head has been changed from %a to %a",nodecodes[getid(oldhead)],nodecodes[getid(head)]) + trace_info("head has been changed from %a to %a",nodecodes[oldhead.id],nodecodes[head.id]) end end return head, true @@ -1302,17 +1271,16 @@ end function vspacing.pagehandler(newhead,where) -- local newhead = texlists.contrib_head if newhead then - newhead = tonut(newhead) local newtail = find_node_tail(newhead) -- best pass that tail, known anyway local flush = false stackhack = true -- todo: only when grid snapping once enabled -- todo: fast check if head = tail for n in traverse_nodes(newhead) do -- we could just look for glue nodes - local id = getid(n) + local id = n.id if id ~= glue_code then flush = true - elseif getsubtype(n) == userskip_code then - if getattr(n,a_skipcategory) then + elseif n.subtype == userskip_code then + if n[a_skipcategory] then stackhack = true else flush = true @@ -1324,36 +1292,35 @@ function vspacing.pagehandler(newhead,where) if flush then if stackhead then if trace_collect_vspacing then report("appending %s nodes to stack (final): %s",newhead) end - setfield(stacktail,"next",newhead) - setfield(newhead,"prev",stacktail) + stacktail.next = newhead + newhead.prev = stacktail newhead = stackhead stackhead, stacktail = nil, nil end if stackhack then stackhack = false if trace_collect_vspacing then report("processing %s nodes: %s",newhead) end - -- texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) - newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) + -- texlists.contrib_head = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) + newhead = collapser(newhead,"page",where,trace_page_vspacing,true,a_snapmethod) else if trace_collect_vspacing then report("flushing %s nodes: %s",newhead) end -- texlists.contrib_head = newhead end - return tonode(newhead) else if stackhead then if trace_collect_vspacing then report("appending %s nodes to stack (intermediate): %s",newhead) end - setfield(stacktail,"next",newhead) - setfield(newhead,"prev",stacktail) + stacktail.next = newhead + newhead.prev = stacktail else if trace_collect_vspacing then report("storing %s nodes in stack (initial): %s",newhead) end stackhead = newhead end stacktail = newtail -- texlists.contrib_head = nil - -- newhead = nil + newhead = nil end end - return nil + return newhead end local ignore = table.tohash { @@ -1363,23 +1330,18 @@ local ignore = table.tohash { } function vspacing.vboxhandler(head,where) - if head and not ignore[where] then - local h = tonut(head) - if getnext(h) then - h = collapser(h,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper - return tonode(h) - end + if head and not ignore[where] and head.next then + head = collapser(head,"vbox",where,trace_vbox_vspacing,true,a_snapvbox) -- todo: local snapper end return head end function vspacing.collapsevbox(n) -- for boxes but using global a_snapmethod - local box = getbox(n) + local box = texgetbox(n) if box then - local list = getlist(box) + local list = box.list if list then - list = collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod) - setfield(box,"list",vpack_node(list)) + box.list = vpack_node(collapser(list,"snapper","vbox",trace_vbox_vspacing,true,a_snapmethod)) end end end @@ -1390,9 +1352,7 @@ end local outer = texnest[0] function vspacing.resetprevdepth() - if texlists.hold_head then - outer.prevdepth = 0 - end + outer.prevdepth = 0 end -- interface diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf Binary files differindex ae09bb5ae..a74501e41 100644 --- a/tex/context/base/status-files.pdf +++ b/tex/context/base/status-files.pdf diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf Binary files differindex 8f1f3e5c8..a591afb75 100644 --- a/tex/context/base/status-lua.pdf +++ b/tex/context/base/status-lua.pdf diff --git a/tex/context/base/status-mkiv.lua b/tex/context/base/status-mkiv.lua index 339bc24f6..caa7dc16c 100644 --- a/tex/context/base/status-mkiv.lua +++ b/tex/context/base/status-mkiv.lua @@ -2014,13 +2014,13 @@ return { { category = "mkiv", filename = "bibl-bib", - loading = "on demand", + loading = "always", status = "pending", }, { category = "mkiv", filename = "bibl-tra", - loading = "on demand", + loading = "always", status = "pending", }, { @@ -2534,60 +2534,6 @@ return { loading = "on demand", status = "okay", }, - { - category = "mkiv", - filename = "publ-ini", - loading = "always", - status = "pending", - }, - { - category = "mkiv", - filename = "publ-old", - loading = "always", - status = "pending", - }, - { - category = "mkiv", - filename = "publ-tra", - loading = "always", - status = "pending", - }, - { - category = "mkiv", - filename = "publ-usr", - loading = "always", - status = "pending", - }, - { - category = "mkiv", - filename = "publ-xml", - loading = "always", - status = "pending", - }, - { - category = "mkiv", - filename = "publ-imp-apa", - loading = "always", - status = "pending", - }, - { - category = "mkiv", - filename = "publ-imp-cite", - loading = "always", - status = "pending", - }, - { - category = "mkiv", - filename = "publ-imp-definitions", - loading = "always", - status = "pending", - }, - { - category = "mkiv", - filename = "publ-imp-commands", - loading = "always", - status = "pending", - }, }, lua = { { @@ -2660,12 +2606,12 @@ return { { category = "lua", filename = "bibl-bib", - loading = "on demand", + status = "todo", }, { category = "lua", filename = "bibl-tra", - loading = "on demand", + status = "todo", }, { category = "lua", @@ -5051,42 +4997,6 @@ return { filename = "x-mathml", status = "todo", }, - { - category = "lua", - filename = "publ-ini", - loading = "publ-ini.mkiv", - status = "pending", - }, - { - category = "lua", - filename = "publ-aut", - loading = "publ-ini.mkiv", - status = "pending", - }, - { - category = "lua", - filename = "publ-dat", - loading = "publ-ini.mkiv", - status = "pending", - }, - { - category = "lua", - filename = "publ-oth", - loading = "publ-ini.mkiv", - status = "pending", - }, - { - category = "lua", - filename = "publ-tra", - loading = "publ-ini.mkiv", - status = "pending", - }, - { - category = "lua", - filename = "publ-usr", - loading = "publ-ini.mkiv", - status = "pending", - }, }, metafun = { { diff --git a/tex/context/base/strc-lst.mkvi b/tex/context/base/strc-lst.mkvi index f78881221..63c3e030a 100644 --- a/tex/context/base/strc-lst.mkvi +++ b/tex/context/base/strc-lst.mkvi @@ -889,7 +889,6 @@ \startsetups[\??listrenderings:abc] \endgraf % are we grouped? -% \advance % yes or no ... \rightskip is also honored \leftskip\listparameter\c!margin % after \endgraf ! \listparameter\c!before \endgraf diff --git a/tex/context/base/strc-mar.lua b/tex/context/base/strc-mar.lua index 258787d0a..b3a6e8f35 100644 --- a/tex/context/base/strc-mar.lua +++ b/tex/context/base/strc-mar.lua @@ -19,27 +19,14 @@ local commands = commands local allocate = utilities.storage.allocate local setmetatableindex = table.setmetatableindex -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getattr = nuts.getattr -local setattr = nuts.setattr -local getbox = nuts.getbox - -local traversenodes = nuts.traverse - +local traversenodes = nodes.traverse local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist local texsetattribute = tex.setattribute +local texgetbox = tex.getbox local a_marks = attributes.private("structure","marks") @@ -119,9 +106,9 @@ end local function sweep(head,first,last) for n in traversenodes(head) do - local id = getid(n) + local id = n.id if id == glyph_code then - local a = getattr(n,a_marks) + local a = n[a_marks] if not a then -- next elseif first == 0 then @@ -131,7 +118,7 @@ local function sweep(head,first,last) end elseif id == hlist_code or id == vlist_code then if boxes_too then - local a = getattr(n,a_marks) + local a = n[a_marks] if not a then -- next elseif first == 0 then @@ -140,7 +127,7 @@ local function sweep(head,first,last) last = a end end - local list = getlist(n) + local list = n.list if list then first, last = sweep(list,first,last) end @@ -156,9 +143,9 @@ setmetatableindex(classes, function(t,k) local s = settings_to_array(k) t[k] = s local lasts = { } function marks.synchronize(class,n,option) - local box = getbox(n) + local box = texgetbox(n) if box then - local first, last = sweep(getlist(box),0,0) + local first, last = sweep(box.list,0,0) if option == v_keep and first == 0 and last == 0 then if trace_marks_get or trace_marks_set then report_marks("action %a, class %a, box %a","retain at synchronize",class,n) diff --git a/tex/context/base/strc-mat.mkiv b/tex/context/base/strc-mat.mkiv index 18cb005cb..b9263cdb0 100644 --- a/tex/context/base/strc-mat.mkiv +++ b/tex/context/base/strc-mat.mkiv @@ -630,13 +630,13 @@ % \prevdepth-\maxdimen % texbook pagina 79-80 % \fi % \noindent % else funny hlist with funny baselineskip -% $$% \Ucheckedstartdisplaymath +% $$% \Ustartdisplaymath % \setdisplaydimensions % \startinnermath} % % \unexpanded\def\stopdisplaymath % {\stopinnermath -% $$% \Ucheckedstopdisplaymath +% $$% \Ustopdisplaymath % \par % \afterdisplayspace % \par @@ -663,13 +663,13 @@ \fi \fi \noindent % else funny hlist with funny baselineskip - \Ucheckedstartdisplaymath + $$% \Ustartdisplaymath \setdisplaydimensions \startinnermath} \unexpanded\def\stopdisplaymath {\stopinnermath - \Ucheckedstopdisplaymath + $$% \Ustopdisplaymath \par \ifvmode \ifcase\c_strc_formulas_space_model diff --git a/tex/context/base/strc-pag.lua b/tex/context/base/strc-pag.lua index fd0a367aa..02ed5610f 100644 --- a/tex/context/base/strc-pag.lua +++ b/tex/context/base/strc-pag.lua @@ -40,19 +40,17 @@ local collected, tobesaved = allocate(), allocate() pages.collected = collected pages.tobesaved = tobesaved -pages.nofpages = 0 local function initializer() collected = pages.collected tobesaved = pages.tobesaved - pages.nofpages = #collected end job.register('structures.pages.collected', tobesaved, initializer) local specification = { } -- to be checked -function pages.save(prefixdata,numberdata,extradata) +function pages.save(prefixdata,numberdata) local realpage = texgetcount("realpageno") local userpage = texgetcount("userpageno") if realpage > 0 then @@ -60,12 +58,10 @@ function pages.save(prefixdata,numberdata,extradata) report_pages("saving page %s.%s",realpage,userpage) end local data = { - number = userpage, - viewerprefix = extradata.viewerprefix, - state = extradata.state, - block = sections.currentblock(), - prefixdata = prefixdata and helpers.simplify(prefixdata), - numberdata = numberdata and helpers.simplify(numberdata), + number = userpage, + block = sections.currentblock(), + prefixdata = prefixdata and helpers.simplify(prefixdata), + numberdata = numberdata and helpers.simplify(numberdata), } tobesaved[realpage] = data if not collected[realpage] then diff --git a/tex/context/base/strc-pag.mkiv b/tex/context/base/strc-pag.mkiv index c4e9819ba..85cfeb40f 100644 --- a/tex/context/base/strc-pag.mkiv +++ b/tex/context/base/strc-pag.mkiv @@ -106,8 +106,6 @@ \let\setuppagenumber\setupuserpagenumber \let\resetpagenumber\resetuserpagenumber -% invisible = - \def\strc_pagenumbers_page_state_save % \normalexpanded? {\ctxlua{structures.pages.save({ prefix = "\namedcounterparameter\s!userpage\c!prefix", @@ -122,9 +120,6 @@ conversionset = "\namedcounterparameter\s!userpage\c!numberconversionset", starter = \!!bs\namedcounterparameter\s!userpage\c!numberstarter\!!es, stopper = \!!bs\namedcounterparameter\s!userpage\c!numberstopper\!!es, - },{ - viewerprefix = \!!bs\namedcounterparameter\s!userpage\c!viewerprefix\!!es, - state = \!!bs\namedcounterparameter\s!userpage\c!state\!!es, } )}} diff --git a/tex/context/base/supp-box.lua b/tex/context/base/supp-box.lua index 3c5a3383d..27078f46f 100644 --- a/tex/context/base/supp-box.lua +++ b/tex/context/base/supp-box.lua @@ -26,118 +26,101 @@ local glue_code = nodecodes.glue local kern_code = nodecodes.kern local glyph_code = nodecodes.glyph -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode +local new_penalty = nodes.pool.penalty +local new_hlist = nodes.pool.hlist +local new_glue = nodes.pool.glue -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getlist = nuts.getlist -local getattribute = nuts.getattribute -local getbox = nuts.getbox - -local setfield = nuts.setfield -local setbox = nuts.setbox - -local free_node = nuts.free -local copy_list = nuts.copy_list -local copy_node = nuts.copy -local find_tail = nuts.tail - -local listtoutf = nodes.listtoutf - -local nodepool = nuts.pool -local new_penalty = nodepool.penalty -local new_hlist = nodepool.hlist -local new_glue = nodepool.glue +local free_node = nodes.free +local copy_list = nodes.copy_list +local copy_node = nodes.copy +local find_tail = nodes.tail +local texsetbox = tex.setbox +local texgetbox = tex.getbox local texget = tex.get -local function hyphenatedlist(head) - local current = head and tonut(head) - while current do - local id = getid(current) - local next = getnext(current) - local prev = getprev(current) +local function hyphenatedlist(list) + while list do + local id, next, prev = list.id, list.next, list.prev if id == disc_code then - local hyphen = getfield(current,"pre") + local hyphen = list.pre if hyphen then local penalty = new_penalty(-500) - -- insert_after etc - setfield(hyphen,"next",penalty) - setfield(penalty,"prev",hyphen) - setfield(prev,"next",hyphen) - setfield(next,"prev", penalty) - setfield(penalty,"next",next) - setfield(hyphen,"prev",prev) - setfield(current,"pre",nil) - free_node(current) + hyphen.next, penalty.prev = penalty, hyphen + prev.next, next.prev = hyphen, penalty + penalty.next, hyphen.prev = next, prev + list.pre = nil + free_node(list) end elseif id == vlist_code or id == hlist_code then - hyphenatedlist(getlist(current)) + hyphenatedlist(list.list) end - current = next + list = next end end commands.hyphenatedlist = hyphenatedlist function commands.showhyphenatedinlist(list) - report_hyphenation("show: %s",listtoutf(tonut(list),false,true)) + report_hyphenation("show: %s",nodes.listtoutf(list,false,true)) end local function checkedlist(list) if type(list) == "number" then - return getlist(getbox(tonut(list))) + return texgetbox(list).list else - return tonut(list) + return list end end -local function applytochars(current,doaction,noaction,nested) +local function applytochars(list,what,nested) + local doaction = context[what or "ruledhbox"] + local noaction = context + local current = checkedlist(list) while current do - local id = getid(current) + local id = current.id if nested and (id == hlist_code or id == vlist_code) then context.beginhbox() - applytochars(getlist(current),what,nested) + applytochars(current.list,what,nested) context.endhbox() elseif id ~= glyph_code then - noaction(tonode(copy_node(current))) + noaction(copy_node(current)) else - doaction(tonode(copy_node(current))) + doaction(copy_node(current)) end - current = getnext(current) + current = current.next end end -local function applytowords(current,doaction,noaction,nested) +local function applytowords(list,what,nested) + local doaction = context[what or "ruledhbox"] + local noaction = context + local current = checkedlist(list) local start while current do - local id = getid(current) + local id = current.id if id == glue_code then if start then - doaction(tonode(copy_list(start,current))) + doaction(copy_list(start,current)) start = nil end - noaction(tonode(copy_node(current))) + noaction(copy_node(current)) elseif nested and (id == hlist_code or id == vlist_code) then context.beginhbox() - applytowords(getlist(current),what,nested) + applytowords(current.list,what,nested) context.egroup() elseif not start then start = current end - current = getnext(current) + current = current.next end if start then - doaction(tonode(copy_list(start))) + doaction(copy_list(start)) end end -commands.applytochars = function(list,what,nested) applytochars(checkedlist(list),context[what or "ruledhbox"],context,nested) end -commands.applytowords = function(list,what,nested) applytowords(checkedlist(list),context[what or "ruledhbox"],context,nested) end +commands.applytochars = applytochars +commands.applytowords = applytowords local split_char = lpeg.Ct(lpeg.C(1)^0) local split_word = lpeg.tsplitat(lpeg.patterns.space) @@ -193,36 +176,36 @@ end local a_vboxtohboxseparator = attributes.private("vboxtohboxseparator") function commands.vboxlisttohbox(original,target,inbetween) - local current = getlist(getbox(original)) + local current = texgetbox(original).list local head = nil local tail = nil while current do - local id = getid(current) - local next = getnext(current) + local id = current.id + local next = current.next if id == hlist_code then - local list = getlist(current) + local list = current.list if head then if inbetween > 0 then local n = new_glue(0,0,inbetween) - setfield(tail,"next",n) - setfield(n,"prev",tail) + tail.next = n + n.prev = tail tail = n end - setfield(tail,"next",list) - setfield(list,"prev",tail) + tail.next = list + list.prev = tail else head = list end tail = find_tail(list) -- remove last separator - if getid(tail) == hlist_code and getattribute(tail,a_vboxtohboxseparator) == 1 then + if tail.id == hlist_code and tail[a_vboxtohboxseparator] == 1 then local temp = tail - local prev = getprev(tail) + local prev = tail.prev if next then - local list = getlist(tail) - setfield(prev,"next",list) - setfield(list,"prev",prev) - setfield(tail,"list",nil) + local list = tail.list + prev.next = list + list.prev = prev + tail.list = nil tail = find_tail(list) else tail = prev @@ -230,21 +213,21 @@ function commands.vboxlisttohbox(original,target,inbetween) free_node(temp) end -- done - setfield(tail,"next",nil) - setfield(current,"list",nil) + tail.next = nil + current.list = nil end current = next end local result = new_hlist() - setfield(result,"list",head) - setbox(target,result) + result.list = head + texsetbox(target,result) end function commands.hboxtovbox(original) - local b = getbox(original) + local b = texgetbox(original) local factor = texget("baselineskip").width / texget("hsize") - setfield(b,"depth",0) - setfield(b,"height",getfield(b,"width") * factor) + b.depth = 0 + b.height = b.width * factor end function commands.boxtostring(n) diff --git a/tex/context/base/supp-mat.mkiv b/tex/context/base/supp-mat.mkiv index 925f25cc4..f77ee3454 100644 --- a/tex/context/base/supp-mat.mkiv +++ b/tex/context/base/supp-mat.mkiv @@ -53,36 +53,6 @@ \let\normalstartdmath \Ustartdisplaymath \let\normalstopdmath \Ustopdisplaymath -% \unexpanded\def\Ustartdisplaymath -% {\ifinner -% \ifhmode -% \normalUstartmath -% \let\Ustopdisplaymath\normalUstopmath -% \else -% \normalUstartdisplaymath -% \let\Ustopdisplaymath\normalUstopdisplaymath -% \fi -% \else -% \normalUstartdisplaymath -% \let\Ustopdisplaymath\normalUstopdisplaymath -% \fi} - -\unexpanded\def\Ucheckedstartdisplaymath - {\ifinner - \ifhmode - \normalUstartmath - \let\Ucheckedstopdisplaymath\normalUstopmath - \else - \normalUstartdisplaymath - \let\Ucheckedstopdisplaymath\normalUstopdisplaymath - \fi - \else - \normalUstartdisplaymath - \let\Ucheckedstopdisplaymath\normalUstopdisplaymath - \fi} - -\let\Ucheckedstopdisplaymath\relax - \def\normalmathaligntab{&} % \let\normalmathaligntab\aligntab does to work well in a let to & (a def works ok) \let\normalsuper \Usuperscript % obsolete @@ -90,8 +60,8 @@ \let\startimath \Ustartmath \let\stopimath \Ustopmath -\let\startdmath \Ustartdisplaymath % \Ucheckedstartdisplaymath -\let\stopdmath \Ustopdisplaymath % \Ucheckedstopdisplaymath +\let\startdmath \Ustartdisplaymath +\let\stopdmath \Ustopmath \unexpanded\def\mathematics#1{\relax \ifmmode#1\else\normalstartimath#1\normalstopimath\fi} \unexpanded\def\displaymath#1{\noindent \ifmmode#1\else\normalstartdmath#1\normalstopdmath\fi} diff --git a/tex/context/base/syst-ini.mkiv b/tex/context/base/syst-ini.mkiv index 38c34556a..ab1c53131 100644 --- a/tex/context/base/syst-ini.mkiv +++ b/tex/context/base/syst-ini.mkiv @@ -246,10 +246,9 @@ % Watch out, for the moment we disable the check for already being defined % later we will revert this but first all chardefs must be replaced. -\normalprotected\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1} -\normalprotected\def\setnewconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number -\normalprotected\def\setconstant {} % dummy, no checking, so it warns -\normalprotected\def\setconstantvalue#1#2{\csname#1\endcsname\numexpr#2\relax} +\normalprotected\def\newconstant #1{\ifdefined#1\let#1\undefined\fi\newcount#1} +\normalprotected\def\setnewconstant#1{\ifdefined#1\let#1\undefined\fi\newcount#1#1} % just a number +\normalprotected\def\setconstant {} % dummy, no checking, so it warns % maybe setconstant with check @@ -745,9 +744,6 @@ \normalprotected\def\settrue #1{\let#1\conditionaltrue } \normalprotected\def\setfalse#1{\let#1\conditionalfalse} -\normalprotected\def\settruevalue #1{\expandafter\let\csname#1\endcsname\conditionaltrue } -\normalprotected\def\setfalsevalue#1{\expandafter\let\csname#1\endcsname\conditionalfalse} - \let\newconditional\setfalse \let\ifconditional \ifcase diff --git a/tex/context/base/tabl-ntb.mkiv b/tex/context/base/tabl-ntb.mkiv index 42c61f16c..a1ae94712 100644 --- a/tex/context/base/tabl-ntb.mkiv +++ b/tex/context/base/tabl-ntb.mkiv @@ -1667,7 +1667,7 @@ \setupTABLE [\c!frameoffset=.5\linewidth, \c!backgroundoffset=\v!frame, - % \c!framecolor=\s!black, + \c!framecolor=\s!black, \c!width=\v!fit, \c!height=\v!fit, \c!autowidth=\v!yes, @@ -1719,7 +1719,7 @@ \setupTABLE [\c!frameoffset=.5\linewidth, \c!backgroundoffset=\v!frame, - % \c!framecolor=\s!black, + \c!framecolor=\s!black, \c!width=\v!fit, \c!height=\v!fit, \c!autowidth=\v!yes, diff --git a/tex/context/base/tabl-tbl.mkiv b/tex/context/base/tabl-tbl.mkiv index 82d1be893..cd5efa7f7 100644 --- a/tex/context/base/tabl-tbl.mkiv +++ b/tex/context/base/tabl-tbl.mkiv @@ -429,8 +429,7 @@ \aligntab \tabl_tabulate_column_vrule_inject \tabl_tabulate_color_side_left -% \tabl_tabulate_inject_pre_skip{\the\s_tabl_tabulate_pre}% - \tabl_tabulate_inject_pre_skip{\the\dimexpr\s_tabl_tabulate_pre}% get rid of plus + \tabl_tabulate_inject_pre_skip{\the\s_tabl_tabulate_pre}% \alignmark\alignmark \aligntab \tabl_tabulate_color_side_both @@ -497,7 +496,7 @@ \egroup \aligntab \noexpand\dostoptagged - \tabl_tabulate_inject_post_skip{\the\dimexpr\s_tabl_tabulate_post}% get rid of plus + \tabl_tabulate_inject_post_skip{\the\s_tabl_tabulate_post}% \alignmark\alignmark }}% \t_tabl_tabulate_dummy\expandafter{\the\t_tabl_tabulate_dummy\NC}% diff --git a/tex/context/base/tabl-xtb.lua b/tex/context/base/tabl-xtb.lua index 653eb6e08..488ef5b78 100644 --- a/tex/context/base/tabl-xtb.lua +++ b/tex/context/base/tabl-xtb.lua @@ -25,21 +25,18 @@ this mechamism will be improved so that it can replace its older cousin. -- todo: use linked list instead of r/c array -local tonumber = tonumber +local commands, context, tex, node = commands, context, tex, node -local commands = commands -local context = context -local tex = tex - -local texgetcount = tex.getcount -local texsetcount = tex.setcount -local texgetdimen = tex.getdimen -local texsetdimen = tex.setdimen -local texget = tex.get +local texgetcount = tex.getcount +local texsetcount = tex.setcount +local texgetbox = tex.getbox +local texgetdimen = tex.getdimen +local texsetdimen = tex.setdimen +local texget = tex.get -local format = string.format -local concat = table.concat -local points = number.points +local format = string.format +local concat = table.concat +local points = number.points local context = context local context_beginvbox = context.beginvbox @@ -52,23 +49,13 @@ local variables = interfaces.variables local setmetatableindex = table.setmetatableindex local settings_to_hash = utilities.parsers.settings_to_hash -local nuts = nodes.nuts -- here nuts gain hardly nothing -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getlist = nuts.getlist -local getfield = nuts.getfield -local getbox = nuts.getbox - -local setfield = nuts.setfield +local copy_node_list = node.copy_list +local hpack_node_list = node.hpack +local vpack_node_list = node.vpack +local slide_node_list = node.slide +local flush_node_list = node.flush_list -local copy_node_list = nuts.copy_list -local hpack_node_list = nuts.hpack -local flush_node_list = nuts.flush_list - -local nodepool = nuts.pool +local nodepool = nodes.pool local new_glue = nodepool.glue local new_kern = nodepool.kern @@ -228,20 +215,20 @@ function xtables.set_reflow_width() while row[c].span do -- can also be previous row ones c = c + 1 end - local tb = getbox("b_tabl_x") + local tb = texgetbox("b_tabl_x") local drc = row[c] -- drc.list = true -- we don't need to keep the content around as we're in trial mode (no: copy_node_list(tb)) -- - local widths, width = data.widths, getfield(tb,"width") + local widths, width = data.widths, tb.width if width > widths[c] then widths[c] = width end - local heights, height = data.heights, getfield(tb,"height") + local heights, height = data.heights, tb.height if height > heights[r] then heights[r] = height end - local depths, depth = data.depths, getfield(tb,"depth") + local depths, depth = data.depths, tb.depth if depth > depths[r] then depths[r] = depth end @@ -332,14 +319,14 @@ function xtables.set_reflow_height() -- while row[c].span do -- we could adapt drc.nx instead -- c = c + 1 -- end - local tb = getbox("b_tabl_x") + local tb = texgetbox("b_tabl_x") local drc = row[c] if data.fixedrows[r] == 0 then -- and drc.dimensionstate < 2 - local heights, height = data.heights, getfield(tb,"height") + local heights, height = data.heights, tb.height if height > heights[r] then heights[r] = height end - local depths, depth = data.depths, getfield(tb,"depth") + local depths, depth = data.depths, tb.depth if depth > depths[r] then depths[r] = depth end @@ -386,7 +373,7 @@ function xtables.set_construct() -- end local drc = row[c] -- this will change as soon as in luatex we can reset a box list without freeing - drc.list = copy_node_list(getbox("b_tabl_x")) + drc.list = copy_node_list(texgetbox("b_tabl_x")) -- c = c + drc.nx - 1 -- data.currentcolumn = c end @@ -659,23 +646,23 @@ function xtables.construct() end local list = drc.list if list then - setfield(list,"shift",getfield(list,"height") + getfield(list,"depth")) + list.shift = list.height + list.depth -- list = hpack_node_list(list) -- is somehow needed - -- setfield(list,"width",0) - -- setfield(list,"height",0) - -- setfield(list,"depth",0) + -- list.width = 0 + -- list.height = 0 + -- list.depth = 0 -- faster: local h = new_hlist() - setfield(h,"list",list) + h.list = list list = h -- if start then - setfield(stop,"next",list) - setfield(list,"prev",stop) + stop.next = list + list.prev = stop else start = list end - stop = list + stop = list -- one node anyway, so not needed: slide_node_list(list) end local step = widths[c] if c < nofcolumns then @@ -683,8 +670,8 @@ function xtables.construct() end local kern = new_kern(step) if stop then - setfield(stop,"next",kern) - setfield(kern,"prev",stop) + stop.next = kern + kern.prev = stop else -- can be first spanning next row (ny=...) start = kern end @@ -693,8 +680,8 @@ function xtables.construct() if start then if rightmargindistance > 0 then local kern = new_kern(rightmargindistance) - setfield(stop,"next",kern) - setfield(kern,"prev",stop) + stop.next = kern + kern.prev = stop -- stop = kern end return start, heights[r] + depths[r], hasspan @@ -734,7 +721,7 @@ function xtables.construct() texsetdimen("global","d_tabl_x_final_width",0) else texsetcount("global","c_tabl_x_state",1) - texsetdimen("global","d_tabl_x_final_width",getfield(body[1][1],"width")) + texsetdimen("global","d_tabl_x_final_width",body[1][1].width) end end @@ -747,8 +734,8 @@ local function inject(row,copy,package) end if package then context_beginvbox() - context(tonode(list)) - context(tonode(new_kern(row[2]))) + context(list) + context(new_kern(row[2])) context_endvbox() context_nointerlineskip() -- figure out a better way if row[4] then @@ -756,13 +743,13 @@ local function inject(row,copy,package) elseif row[3] then context_blank(row[3] .. "sp") -- why blank ? else - context(tonode(new_glue(0))) + context(new_glue(0)) end else - context(tonode(list)) - context(tonode(new_kern(row[2]))) + context(list) + context(new_kern(row[2])) if row[3] then - context(tonode(new_glue(row[3]))) + context(new_glue(row[3])) end end end @@ -835,7 +822,7 @@ function xtables.flush(directives) -- todo split by size / no inbetween then .. inject(head[i],repeatheader) end if rowdistance > 0 then - context(tonode(new_glue(rowdistance))) + context(new_glue(rowdistance)) end if not repeatheader then results[head_mode] = { } @@ -848,7 +835,7 @@ function xtables.flush(directives) -- todo split by size / no inbetween then .. inject(more[i],true) end if rowdistance > 0 then - context(tonode(new_glue(rowdistance))) + context(new_glue(rowdistance)) end end elseif headsize > 0 and repeatheader then -- following chunk gets head @@ -858,7 +845,7 @@ function xtables.flush(directives) -- todo split by size / no inbetween then .. inject(head[i],true) end if rowdistance > 0 then - context(tonode(new_glue(rowdistance))) + context(new_glue(rowdistance)) end end else -- following chunk gets nothing @@ -885,7 +872,7 @@ function xtables.flush(directives) -- todo split by size / no inbetween then .. -- all is flushed and footer fits if footsize > 0 then if rowdistance > 0 then - context(tonode(new_glue(rowdistance))) + context(new_glue(rowdistance)) end for i=1,#foot do inject(foot[i]) @@ -899,7 +886,7 @@ function xtables.flush(directives) -- todo split by size / no inbetween then .. -- todo: try to flush a few more lines if repeatfooter and footsize > 0 then if rowdistance > 0 then - context(tonode(new_glue(rowdistance))) + context(new_glue(rowdistance)) end for i=1,#foot do inject(foot[i],true) @@ -951,13 +938,13 @@ function xtables.flush(directives) -- todo split by size / no inbetween then .. inject(head[i]) end if #head > 0 and rowdistance > 0 then - context(tonode(new_glue(rowdistance))) + context(new_glue(rowdistance)) end for i=1,#body do inject(body[i]) end if #foot > 0 and rowdistance > 0 then - context(tonode(new_glue(rowdistance))) + context(new_glue(rowdistance)) end for i=1,#foot do inject(foot[i]) @@ -977,24 +964,6 @@ function xtables.cleanup() flush_node_list(r[1]) end end - - -- local rows = data.rows - -- for i=1,#rows do - -- local row = rows[i] - -- for i=1,#row do - -- local cell = row[i] - -- local list = cell.list - -- if list then - -- cell.width = getfield(list,"width") - -- cell.height = getfield(list,"height") - -- cell.depth = getfield(list,"depth") - -- cell.list = true - -- end - -- end - -- end - -- data.result = nil - -- inspect(data) - data = table.remove(stack) end diff --git a/tex/context/base/task-ini.lua b/tex/context/base/task-ini.lua index fa9b0cf10..3447214bd 100644 --- a/tex/context/base/task-ini.lua +++ b/tex/context/base/task-ini.lua @@ -35,7 +35,6 @@ appendaction("processors", "characters", "typesetters.cases.handler") appendaction("processors", "characters", "typesetters.breakpoints.handler") -- disabled appendaction("processors", "characters", "scripts.injectors.handler") -- disabled -appendaction("processors", "words", "languages.replacements.handler") -- disabled appendaction("processors", "words", "builders.kernel.hyphenation") -- always on appendaction("processors", "words", "languages.words.check") -- disabled -- might move up, no disc check needed then @@ -58,7 +57,6 @@ appendaction("processors", "lists", "typesetters.digits.handler") appendaction("processors", "lists", "typesetters.italics.handler") -- disabled (after otf/kern handling) ------------("processors", "lists", "typesetters.initials.handler") -- disabled -appendaction("shipouts", "normalizers", "builders.paragraphs.expansion.trace") -- disabled appendaction("shipouts", "normalizers", "nodes.handlers.cleanuppage") -- disabled appendaction("shipouts", "normalizers", "typesetters.alignments.handler") appendaction("shipouts", "normalizers", "nodes.references.handler") -- disabled @@ -117,12 +115,11 @@ appendaction("vboxbuilders", "normalizers", "builders.vspacing.vboxhandler") -- experimental too -appendaction("mvlbuilders", "normalizers", "typesetters.checkers.handler") -appendaction("vboxbuilders", "normalizers", "typesetters.checkers.handler") +appendaction("mvlbuilders", "normalizers","typesetters.checkers.handler") +appendaction("vboxbuilders","normalizers","typesetters.checkers.handler") -- speedup: only kick in when used -disableaction("processors", "languages.replacements.handler") disableaction("processors", "typesetters.characteralign.handler") disableaction("processors", "scripts.autofontfeature.handler") disableaction("processors", "scripts.splitters.handler") @@ -143,7 +140,6 @@ disableaction("processors", "typesetters.kerns.handler") disableaction("processors", "typesetters.italics.handler") disableaction("processors", "nodes.handlers.stripping") -disableaction("shipouts", "builders.paragraphs.expansion.trace") disableaction("shipouts", "typesetters.alignments.handler") disableaction("shipouts", "nodes.rules.handler") disableaction("shipouts", "nodes.shifts.handler") diff --git a/tex/context/base/trac-inf.lua b/tex/context/base/trac-inf.lua index 067cff27c..802f2e667 100644 --- a/tex/context/base/trac-inf.lua +++ b/tex/context/base/trac-inf.lua @@ -123,10 +123,7 @@ function statistics.show() -- this code will move local register = statistics.register register("used platform", function() - local mask = lua.mask or "ascii" - return format("%s, type: %s, binary subtree: %s, symbol mask: %s (%s)", - os.platform or "unknown",os.type or "unknown", environment.texos or "unknown", - mask,mask == "utf" and "τεχ" or "tex") + return format("%s, type: %s, binary subtree: %s",os.platform or "unknown",os.type or "unknown", environment.texos or "unknown") end) register("luatex banner", function() return lower(status.banner) diff --git a/tex/context/base/trac-jus.lua b/tex/context/base/trac-jus.lua index 00c871159..38220a752 100644 --- a/tex/context/base/trac-jus.lua +++ b/tex/context/base/trac-jus.lua @@ -14,30 +14,14 @@ typesetters.checkers = checkers local a_alignstate = attributes.private("alignstate") local a_justification = attributes.private("justification") -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getlist = nuts.getlist -local getattr = nuts.getattr -local setattr = nuts.setattr -local setlist = nuts.setlist - -local traverse_id = nuts.traverse_id -local get_list_dimensions = nuts.dimensions -local linked_nodes = nuts.linked -local copy_node = nuts.copy - -local tracedrule = nodes.tracers.pool.nuts.rule - -local nodepool = nuts.pool - -local new_rule = nodepool.rule -local new_hlist = nodepool.hlist -local new_glue = nodepool.glue -local new_kern = nodepool.kern - +local tracers = nodes.tracers +local tracedrule = tracers.rule + +local new_rule = nodes.pool.rule +local new_hlist = nodes.pool.hlist +local new_glue = nodes.pool.glue +local new_kern = nodes.pool.kern +local get_list_dimensions = node.dimensions local hlist_code = nodes.nodecodes.hlist local texsetattribute = tex.setattribute @@ -75,35 +59,34 @@ trackers.register("visualizers.justification", function(v) end) function checkers.handler(head) - for current in traverse_id(hlist_code,tonut(head)) do - if getattr(current,a_justification) == 1 then - setattr(current,a_justification,0) - local width = getfield(current,"width") + for current in node.traverse_id(hlist_code,head) do + if current[a_justification] == 1 then + current[a_justification] = 0 + local width = current.width if width > 0 then - local list = getlist(current) + local list = current.list if list then local naturalwidth, naturalheight, naturaldepth = get_list_dimensions(list) local delta = naturalwidth - width if naturalwidth == 0 or delta == 0 then -- special box elseif delta >= max_threshold then - local rule = tracedrule(delta,naturalheight,naturaldepth,getfield(list,"glue_set") == 1 and "trace:dr" or "trace:db") - setfield(current,"list",linked_nodes(list,new_hlist(rule))) + local rule = tracedrule(delta,naturalheight,naturaldepth,list.glue_set == 1 and "trace:dr"or "trace:db") + current.list = list .. new_hlist(rule) elseif delta <= min_threshold then - local alignstate = getattr(list,a_alignstate) + local alignstate = list[a_alignstate] if alignstate == 1 then local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dc") - setfield(current,"list",linked_nodes(new_hlist(rule),list)) + current.list = new_hlist(rule) .. list elseif alignstate == 2 then - local lrule = tracedrule(-delta/2,naturalheight,naturaldepth,"trace:dy") - local rrule = copy_node(lrule) - setfield(current,"list",linked_nodes(new_hlist(lrule),list,new_kern(delta/2),new_hlist(rrule))) + local rule = tracedrule(-delta/2,naturalheight,naturaldepth,"trace:dy") + current.list = new_hlist(rule^1) .. list .. new_kern(delta/2) .. new_hlist(rule) elseif alignstate == 3 then local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dm") - setfield(current,"list",linked_nodes(list,new_kern(delta),new_hlist(rule))) + current.list = list .. new_kern(delta) .. new_hlist(rule) else local rule = tracedrule(-delta,naturalheight,naturaldepth,"trace:dg") - setfield(current,"list",linked_nodes(list,new_kern(delta),new_hlist(rule))) + current.list = list .. new_kern(delta) .. new_hlist(rule) end end end diff --git a/tex/context/base/trac-par.lua b/tex/context/base/trac-par.lua index aab57ce5c..262a9cc33 100644 --- a/tex/context/base/trac-par.lua +++ b/tex/context/base/trac-par.lua @@ -1,25 +1,8 @@ -if not modules then modules = { } end modules ['trac-par'] = { - version = 1.001, - comment = "companion to node-par.mkiv", - author = "Hans Hagen", - copyright = "ConTeXt Development Team", - license = "see context related readme files", - comment = "a translation of the built in parbuilder, initial convertsin by Taco Hoekwater", -} +-- for the moment here: local utfchar = utf.char local concat = table.concat -local nuts = nodes.nuts -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getid = nuts.getid -local getnext = nuts.getnext -local getlist = nuts.getlist -local getfont = nuts.getfont -local getchar = nuts.getchar - local nodecodes = nodes.nodecodes local hlist_code = nodecodes.hlist local vlist_code = nodecodes.vlist @@ -59,14 +42,14 @@ local function colorize(n) -- tricky: the built-in method creates dummy fonts and the last line normally has the -- original font and that one then has ex.auto set while n do - local id = getid(n) + local id = n.id if id == glyph_code then - local ne = getfield(n,"expansion_factor") + local ne = n.expansion_factor if ne == 0 then if length > 0 then flush() end setnodecolor(n,"hz:zero") else - local f = getfont(n) + local f = n.font if f ~= font then if length > 0 then flush() @@ -96,8 +79,8 @@ local function colorize(n) end if trace_verbose then length = length + 1 - list[length] = utfchar(getchar(n)) - width = width + getfield(n,"width") -- no kerning yet + list[length] = utfchar(n.char) + width = width + n.width -- no kerning yet end end end @@ -105,13 +88,13 @@ local function colorize(n) if length > 0 then flush() end - colorize(getlist(n),flush) + colorize(n.list,flush) else -- nothing to show on kerns if length > 0 then flush() end end - n = getnext(n) + n = n.next end if length > 0 then flush() @@ -121,14 +104,14 @@ end builders.paragraphs.expansion = builders.paragraphs.expansion or { } function builders.paragraphs.expansion.trace(head) - colorize(tonut(head),true) + colorize(head,true) return head end local tasks = nodes.tasks --- tasks.prependaction("shipouts","normalizers","builders.paragraphs.expansion.trace") --- tasks.disableaction("shipouts","builders.paragraphs.expansion.trace") +tasks.prependaction("shipouts","normalizers","builders.paragraphs.expansion.trace") +tasks.disableaction("shipouts","builders.paragraphs.expansion.trace") local function set(v) if v then diff --git a/tex/context/base/trac-pro.lua b/tex/context/base/trac-pro.lua index 897b6a15c..d6e0d0339 100644 --- a/tex/context/base/trac-pro.lua +++ b/tex/context/base/trac-pro.lua @@ -26,8 +26,7 @@ local registered = { } local function report_index(k,name) if trace_namespaces then - report_system("reference to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) + report_system("reference to %a in protected namespace %a: %s",k,name,debug.traceback()) else report_system("reference to %a in protected namespace %a",k,name) end @@ -35,8 +34,7 @@ end local function report_newindex(k,name) if trace_namespaces then - report_system("assignment to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) + report_system("assignment to %a in protected namespace %a: %s",k,name,debug.traceback()) else report_system("assignment to %a in protected namespace %a",k,name) end diff --git a/tex/context/base/trac-tim.lua b/tex/context/base/trac-tim.lua index b4744291c..15ac9bf1b 100644 --- a/tex/context/base/trac-tim.lua +++ b/tex/context/base/trac-tim.lua @@ -88,7 +88,7 @@ local function convert(name) delta = factor/delta end for k=1,#s do - s[k] = format("(%.3f,%.3f)",k,(s[k]-b)*delta) + s[k] = format("(%s,%s)",k,(s[k]-b)*delta) end paths[tagname] = concat(s,"--") end diff --git a/tex/context/base/trac-vis.lua b/tex/context/base/trac-vis.lua index 420e9a00d..dc8bcc5e7 100644 --- a/tex/context/base/trac-vis.lua +++ b/tex/context/base/trac-vis.lua @@ -34,7 +34,6 @@ local formatters = string.formatters -- todo: inline concat (more efficient) local nodecodes = nodes.nodecodes -local disc_code = nodecodes.disc local kern_code = nodecodes.kern local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist @@ -59,41 +58,21 @@ local rightskip_code = gluecodes.rightskip local whatsitcodes = nodes.whatsitcodes -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local setfield = nuts.setfield -local getattr = nuts.getattr -local setattr = nuts.setattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getbox = nuts.getbox -local getlist = nuts.getlist -local getleader = nuts.getleader - -local hpack_nodes = nuts.hpack -local vpack_nodes = nuts.vpack -local copy_node = nuts.copy -local copy_list = nuts.copy_list -local free_node = nuts.free -local free_node_list = nuts.flush_list -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local traverse_nodes = nuts.traverse -local linked_nodes = nuts.linked - -local fast_hpack = nuts.fasthpack -local fast_hpack_string = nuts.typesetters.fast_hpack +local hpack_nodes = node.hpack +local vpack_nodes = node.vpack +local fast_hpack_string = nodes.typesetters.fast_hpack +local copy_node = node.copy +local copy_list = node.copy_list +local free_node = node.free +local free_node_list = node.flush_list +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local fast_hpack = nodes.fasthpack +local traverse_nodes = node.traverse local texgetattribute = tex.getattribute local texsetattribute = tex.setattribute - +local texgetbox = tex.getbox local unsetvalue = attributes.unsetvalue local current_font = font.current @@ -102,7 +81,7 @@ local exheights = fonts.hashes.exheights local emwidths = fonts.hashes.emwidths local pt_factor = number.dimenfactors.pt -local nodepool = nuts.pool +local nodepool = nodes.pool local new_rule = nodepool.rule local new_kern = nodepool.kern local new_glue = nodepool.glue @@ -314,39 +293,39 @@ local c_white_d = "trace:dw" local function sometext(str,layer,color,textcolor) -- we can just paste verbatim together .. no typesteting needed local text = fast_hpack_string(str,usedfont) - local size = getfield(text,"width") + local size = text.width local rule = new_rule(size,2*exheight,exheight/2) local kern = new_kern(-size) if color then setcolor(rule,color) end if textcolor then - setlistcolor(getlist(text),textcolor) + setlistcolor(text.list,textcolor) end - local info = linked_nodes(rule,kern,text) + local info = rule .. kern .. text setlisttransparency(info,c_zero) info = fast_hpack(info) if layer then - setattr(info,a_layer,layer) + info[a_layer] = layer end - local width = getfield(info,"width") - setfield(info,"width",0) - setfield(info,"height",0) - setfield(info,"depth",0) + local width = info.width + info.width = 0 + info.height = 0 + info.depth = 0 return info, width end local f_cache = { } local function fontkern(head,current) - local kern = getfield(current,"kern") + local kern = current.kern local info = f_cache[kern] if info then -- print("hit fontkern") else local text = fast_hpack_string(formatters[" %0.3f"](kern*pt_factor),usedfont) local rule = new_rule(emwidth/10,6*exheight,2*exheight) - local list = getlist(text) + local list = text.list if kern > 0 then setlistcolor(list,c_positive_d) elseif kern < 0 then @@ -356,12 +335,13 @@ local function fontkern(head,current) end setlisttransparency(list,c_text_d) settransparency(rule,c_text_d) - setfield(text,"shift",-5 * exheight) - info = fast_hpack(linked_nodes(rule,text)) - setattr(info,a_layer,l_fontkern) - setfield(info,"width",0) - setfield(info,"height",0) - setfield(info,"depth",0) + text.shift = -5 * exheight + info = rule .. text + info = fast_hpack(info) + info[a_layer] = l_fontkern + info.width = 0 + info.height = 0 + info.depth = 0 f_cache[kern] = info end head = insert_node_before(head,current,copy_list(info)) @@ -402,7 +382,7 @@ local tags = { } local function whatsit(head,current) - local what = getsubtype(current) + local what = current.subtype local info = w_cache[what] if info then -- print("hit whatsit") @@ -410,7 +390,7 @@ local function whatsit(head,current) local tag = whatsitcodes[what] -- maybe different text colors per tag info = sometext(formatters["W:%s"](tag and tags[tag] or what),usedfont,nil,c_white) - setattr(info,a_layer,l_whatsit) + info[a_layer] = l_whatsit w_cache[what] = info end head, current = insert_node_after(head,current,copy_list(info)) @@ -418,13 +398,13 @@ local function whatsit(head,current) end local function user(head,current) - local what = getsubtype(current) + local what = current.subtype local info = w_cache[what] if info then -- print("hit user") else info = sometext(formatters["U:%s"](what),usedfont) - setattr(info,a_layer,l_user) + info[a_layer] = l_user w_cache[what] = info end head, current = insert_node_after(head,current,copy_list(info)) @@ -434,14 +414,14 @@ end local b_cache = { } local function ruledbox(head,current,vertical,layer,what,simple,previous) - local wd = getfield(current,"width") + local wd = current.width if wd ~= 0 then - local ht = getfield(current,"height") - local dp = getfield(current,"depth") - local next = getnext(current) - local prev = previous -- getprev(current) ... prev can be wrong in math mode - setfield(current,"next",nil) - setfield(current,"prev",nil) + local ht = current.height + local dp = current.depth + local next = current.next + local prev = previous -- current.prev ... prev can be wrong in math mode + current.next = nil + current.prev = nil local linewidth = emwidth/10 local baseline, baseskip if dp ~= 0 and ht ~= 0 then @@ -450,16 +430,16 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous) if not baseline then -- due to an optimized leader color/transparency we need to set the glue node in order -- to trigger this mechanism - local leader = linked_nodes(new_glue(2*linewidth),new_rule(6*linewidth,linewidth,0),new_glue(2*linewidth)) + local leader = new_glue(2*linewidth) .. new_rule(6*linewidth,linewidth,0) .. new_glue(2*linewidth) -- setlisttransparency(leader,c_text) leader = fast_hpack(leader) -- setlisttransparency(leader,c_text) baseline = new_glue(0) - setfield(baseline,"leader",leader) - setfield(baseline,"subtype",cleaders_code) - local spec = getfield(baseline,"spec") - setfield(spec,"stretch",65536) - setfield(spec,"stretch_order",2) + baseline.leader = leader + baseline.subtype = cleaders_code + local spec = baseline.spec + spec.stretch = 65536 + spec.stretch_order = 2 setlisttransparency(baseline,c_text) b_cache.baseline = baseline end @@ -481,49 +461,47 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous) this = b_cache[what] if not this then local text = fast_hpack_string(what,usedfont) - this = linked_nodes(new_kern(-getfield(text,"width")),text) + this = new_kern(-text.width) .. text setlisttransparency(this,c_text) this = fast_hpack(this) - setfield(this,"width",0) - setfield(this,"height",0) - setfield(this,"depth",0) + this.width = 0 + this.height = 0 + this.depth = 0 b_cache[what] = this end end -- we need to trigger the right mode (else sometimes no whatits) - local info = linked_nodes( - this and copy_list(this) or nil, - new_rule(linewidth,ht,dp), - new_rule(wd-2*linewidth,-dp+linewidth,dp), - new_rule(linewidth,ht,dp), - new_kern(-wd+linewidth), + local info = + (this and copy_list(this) or nil) .. + new_rule(linewidth,ht,dp) .. + new_rule(wd-2*linewidth,-dp+linewidth,dp) .. + new_rule(linewidth,ht,dp) .. + new_kern(-wd+linewidth) .. new_rule(wd-2*linewidth,ht,-ht+linewidth) - ) if baseskip then - info = linked_nodes(info,baseskip,baseline) + info = info .. baseskip .. baseline end setlisttransparency(info,c_text) info = fast_hpack(info) - setfield(info,"width",0) - setfield(info,"height",0) - setfield(info,"depth",0) - setattr(info,a_layer,layer) - local info = linked_nodes(current,new_kern(-wd),info) + info.width = 0 + info.height = 0 + info.depth = 0 + info[a_layer] = layer + local info = current .. new_kern(-wd) .. info info = fast_hpack(info,wd) if vertical then info = vpack_nodes(info) end if next then - setfield(info,"next",next) - setfield(next,"prev",info) + info.next = next + next.prev = info end if prev then - if getid(prev) == gluespec_code then - report_visualize("ignoring invalid prev") - -- weird, how can this happen, an inline glue-spec, probably math + if prev.id == gluespec_code then + -- weird, how can this happen, an inline glue-spec else - setfield(info,"prev",prev) - setfield(prev,"next",info) + info.prev = prev + prev.next = info end end if head == current then @@ -537,14 +515,14 @@ local function ruledbox(head,current,vertical,layer,what,simple,previous) end local function ruledglyph(head,current,previous) - local wd = getfield(current,"width") + local wd = current.width if wd ~= 0 then - local ht = getfield(current,"height") - local dp = getfield(current,"depth") - local next = getnext(current) + local ht = current.height + local dp = current.depth + local next = current.next local prev = previous - setfield(current,"next",nil) - setfield(current,"prev",nil) + current.next = nil + current.prev = nil local linewidth = emwidth/20 local baseline if dp ~= 0 and ht ~= 0 then @@ -552,32 +530,31 @@ local function ruledglyph(head,current,previous) end local doublelinewidth = 2*linewidth -- could be a pdf rule - local info = linked_nodes( - new_rule(linewidth,ht,dp), - new_rule(wd-doublelinewidth,-dp+linewidth,dp), - new_rule(linewidth,ht,dp), - new_kern(-wd+linewidth), - new_rule(wd-doublelinewidth,ht,-ht+linewidth), - new_kern(-wd+doublelinewidth), + local info = + new_rule(linewidth,ht,dp) .. + new_rule(wd-doublelinewidth,-dp+linewidth,dp) .. + new_rule(linewidth,ht,dp) .. + new_kern(-wd+linewidth) .. + new_rule(wd-doublelinewidth,ht,-ht+linewidth) .. + new_kern(-wd+doublelinewidth) .. baseline - ) setlistcolor(info,c_glyph) setlisttransparency(info,c_glyph_d) info = fast_hpack(info) - setfield(info,"width",0) - setfield(info,"height",0) - setfield(info,"depth",0) - setattr(info,a_layer,l_glyph) - local info = linked_nodes(current,new_kern(-wd),info) + info.width = 0 + info.height = 0 + info.depth = 0 + info[a_layer] = l_glyph + local info = current .. new_kern(-wd) .. info info = fast_hpack(info) - setfield(info,"width",wd) + info.width = wd if next then - setfield(info,"next",next) - setfield(next,"prev",info) + info.next = next + next.prev = info end if prev then - setfield(info,"prev",prev) - setfield(prev,"next",info) + info.prev = prev + prev.next = info end if head == current then return info, info @@ -622,9 +599,9 @@ local tags = { -- we sometimes pass previous as we can have issues in math (not watertight for all) local function ruledglue(head,current,vertical) - local spec = getfield(current,"spec") - local width = getfield(spec,"width") - local subtype = getsubtype(current) + local spec = current.spec + local width = spec.width + local subtype = current.subtype local amount = formatters["%s:%0.3f"](tags[subtype] or (vertical and "VS") or "HS",width*pt_factor) local info = g_cache[amount] if info then @@ -652,13 +629,13 @@ local function ruledglue(head,current,vertical) info = vpack_nodes(info) end head, current = insert_node_before(head,current,info) - return head, getnext(current) + return head, current.next end local k_cache = { } local function ruledkern(head,current,vertical) - local kern = getfield(current,"kern") + local kern = current.kern local info = k_cache[kern] if info then -- print("kern hit") @@ -678,13 +655,13 @@ local function ruledkern(head,current,vertical) info = vpack_nodes(info) end head, current = insert_node_before(head,current,info) - return head, getnext(current) + return head, current.next end local p_cache = { } local function ruledpenalty(head,current,vertical) - local penalty = getfield(current,"penalty") + local penalty = current.penalty local info = p_cache[penalty] if info then -- print("penalty hit") @@ -704,7 +681,7 @@ local function ruledpenalty(head,current,vertical) info = vpack_nodes(info) end head, current = insert_node_before(head,current,info) - return head, getnext(current) + return head, current.next end local function visualize(head,vertical) @@ -725,8 +702,8 @@ local function visualize(head,vertical) local attr = unsetvalue local prev_trace_fontkern = nil while current do - local id = getid(current) - local a = getattr(current,a_visual) or unsetvalue + local id = current.id + local a = current[a_visual] or unsetvalue if a ~= attr then prev_trace_fontkern = trace_fontkern if a == unsetvalue then @@ -759,30 +736,30 @@ local function visualize(head,vertical) attr = a end if trace_strut then - setattr(current,a_layer,l_strut) + current[a_layer] = l_strut elseif id == glyph_code then if trace_glyph then head, current = ruledglyph(head,current,previous) end elseif id == disc_code then if trace_glyph then - local pre = getfield(current,"pre") + local pre = current.pre if pre then - setfield(current,"pre",ruledglyph(pre,pre)) + current.pre = ruledglyph(pre,pre) end - local post = getfield(current,"post") + local post = current.post if post then - setfield(current,"post",ruledglyph(post,post)) + current.post = ruledglyph(post,post) end - local replace = getfield(current,"replace") + local replace = current.replace if replace then - setfield(current,"replace",ruledglyph(replace,replace)) + current.replace = ruledglyph(replace,replace) end end elseif id == kern_code then - local subtype = getsubtype(current) + local subtype = current.subtype -- tricky ... we don't copy the trace attribute in node-inj (yet) - if subtype == font_kern_code or getattr(current,a_fontkern) then + if subtype == font_kern_code or current[a_fontkern] then if trace_fontkern or prev_trace_fontkern then head, current = fontkern(head,current) end @@ -792,9 +769,9 @@ local function visualize(head,vertical) end end elseif id == glue_code then - local content = getleader(current) + local content = current.leader if content then - setfield(current,"leader",visualize(content,false)) + current.leader = visualize(content,false) elseif trace_glue then head, current = ruledglue(head,current,vertical) end @@ -803,21 +780,21 @@ local function visualize(head,vertical) head, current = ruledpenalty(head,current,vertical) end elseif id == disc_code then - setfield(current,"pre",visualize(getfield(current,"pre"))) - setfield(current,"post",isualize(getfield(current,"post"))) - setfield(current,"replace",visualize(getfield(current,"replace"))) + current.pre = visualize(current.pre) + current.post = visualize(current.post) + current.replace = visualize(current.replace) elseif id == hlist_code then - local content = getlist(current) + local content = current.list if content then - setfield(current,"list",visualize(content,false)) + current.list = visualize(content,false) end if trace_hbox then head, current = ruledbox(head,current,false,l_hbox,"H__",trace_simple,previous) end elseif id == vlist_code then - local content = getlist(current) + local content = current.list if content then - setfield(current,"list",visualize(content,true)) + current.list = visualize(content,true) end if trace_vtop then head, current = ruledbox(head,current,true,l_vtop,"_T_",trace_simple,previous) @@ -834,7 +811,7 @@ local function visualize(head,vertical) end end previous = current - current = getnext(current) + current = current.next end return head end @@ -863,36 +840,25 @@ local function cleanup() -- report_visualize("cache: %s fontkerns, %s skips, %s penalties, %s kerns, %s whatsits, %s boxes",nf,ng,np,nk,nw,nb) end -local function handler(head) +function visualizers.handler(head) if usedfont then starttiming(visualizers) -- local l = texgetattribute(a_layer) -- local v = texgetattribute(a_visual) -- texsetattribute(a_layer,unsetvalue) -- texsetattribute(a_visual,unsetvalue) - head = visualize(tonut(head)) + head = visualize(head) -- texsetattribute(a_layer,l) -- texsetattribute(a_visual,v) -- -- cleanup() stoptiming(visualizers) - return tonode(head), true - else - return head, false end + return head, false end -visualizers.handler = handler - function visualizers.box(n) - if usedfont then - starttiming(visualizers) - local box = getbox(n) - setfield(box,"list",visualize(getlist(box))) - stoptiming(visualizers) - return head, true - else - return head, false - end + local box = texgetbox(n) + box.list = visualizers.handler(box.list) end local last = nil @@ -906,9 +872,9 @@ local mark = { local function markfonts(list) for n in traverse_nodes(list) do - local id = getid(n) + local id = n.id if id == glyph_code then - local font = getfont(n) + local font = n.font local okay = used[font] if not okay then last = last + 1 @@ -917,14 +883,14 @@ local function markfonts(list) end setcolor(n,okay) elseif id == hlist_code or id == vlist_code then - markfonts(getlist(n)) + markfonts(n.list) end end end function visualizers.markfonts(list) last, used = 0, { } - markfonts(type(n) == "number" and getlist(getbox(n)) or n) + markfonts(type(n) == "number" and texgetbox(n).list or n) end function commands.markfonts(n) diff --git a/tex/context/base/type-imp-buy.mkiv b/tex/context/base/type-imp-buy.mkiv index dbfffe57c..9815cc44b 100644 --- a/tex/context/base/type-imp-buy.mkiv +++ b/tex/context/base/type-imp-buy.mkiv @@ -11,125 +11,27 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -% monotype sabon - \starttypescriptcollection[sabon] - \starttypescript [serif] [sabon] [name] - % - \definefontsynonym [Serif] [SabonMT] - \definefontsynonym [SerifItalic] [SabonMT-Italic] - \definefontsynonym [SerifSlanted] [SabonMT-Italic] - \definefontsynonym [SerifBold] [SabonMT-SemiBold] - \definefontsynonym [SerifBoldItalic] [SabonMT-SemiBoldItalic] - \definefontsynonym [SerifBoldSlanted][SabonMT-SemiBoldItalic] - \definefontsynonym [SerifCaps] [SabonMT-RegularSC] - % - \definefontsynonym[SabonMT] [sab_____] - \definefontsynonym[SabonMT-Italic] [sabi____] - \definefontsynonym[SabonMT-ItalicOsF] [saboi___] - \definefontsynonym[SabonMT-SemiBoldOsF] [sabos___] - \definefontsynonym[SabonMT-SemiBold] [sabs____] - \definefontsynonym[SabonMT-RegularSC] [sabsc___] - \definefontsynonym[SabonMT-SemiBoldItalic] [sabsi___] - \definefontsynonym[SabonMT-SemiBoldItalicOsF][sasio___] - % - \stoptypescript +\starttypescript [serif] [sabon] [name] + + \definefontsynonym [Serif] [SabonMT] + \definefontsynonym [SerifItalic] [SabonMT-Italic] + \definefontsynonym [SerifSlanted] [SabonMT-Italic] + \definefontsynonym [SerifBold] [SabonMT-SemiBold] + \definefontsynonym [SerifBoldItalic] [SabonMT-SemiBoldItalic] + \definefontsynonym [SerifBoldSlanted] [SabonMT-SemiBoldItalic] + \definefontsynonym [SerifCaps] [SabonMT-RegularSC] + + \definefontsynonym[SabonMT] [sab_____] + \definefontsynonym[SabonMT-Italic] [sabi____] + \definefontsynonym[SabonMT-ItalicOsF] [saboi___] + \definefontsynonym[SabonMT-SemiBoldOsF] [sabos___] + \definefontsynonym[SabonMT-SemiBold] [sabs____] + \definefontsynonym[SabonMT-RegularSC] [sabsc___] + \definefontsynonym[SabonMT-SemiBoldItalic] [sabsi___] + \definefontsynonym[SabonMT-SemiBoldItalicOsF][sasio___] +\stoptypescript \stoptypescriptcollection -% itc stone - -\starttypescriptcollection[stone] - - \starttypescript [sans] [stone] [name] - % - \definefontsynonym [Sans] [StoneSansITC-Medium] - \definefontsynonym [SansItalic] [StoneSansITC-MediumItalic] - \definefontsynonym [SansSlanted] [StoneSansITC-MediumItalic] - \definefontsynonym [SansBold] [StoneSansITC-Bold] - \definefontsynonym [SansBoldItalic] [StoneSansITC-BoldItalic] - \definefontsynonym [SansBoldSlanted][StoneSansITC-BoldItalic] - \definefontsynonym [SansCaps] [StoneSansSCITC-Medium] - % - \definefontsynonym[StoneSansITC-Bold] [stosnb] - \definefontsynonym[StoneSansITC-BoldItalic] [stosnbi] - \definefontsynonym[StoneSansITC-Medium] [stosnm] - \definefontsynonym[StoneSansITC-MediumItalic][stosnmi] - \definefontsynonym[StoneSansSemITC-Semi] [stosns] - \definefontsynonym[StoneSansSemITC-SemiIta] [stosnsi] - \definefontsynonym[StoneSansSCITC-Medium] [stosnscm] - \definefontsynonym[StoneSansSemSCITC-Semi] [stosnscs] - % - \stoptypescript - - \starttypescript [serif] [stone] [name] - % - \definefontsynonym [Serif] [StoneSerifITC-Medium] - \definefontsynonym [SerifItalic] [StoneSerifITC-MediumItalic] - \definefontsynonym [SerifSlanted] [StoneSerifITC-MediumItalic] - \definefontsynonym [SerifBold] [StoneSerifITC-Bold] - \definefontsynonym [SerifBoldItalic] [StoneSerifITC-BoldItalic] - \definefontsynonym [SerifBoldSlanted][StoneSerifITC-BoldItalic] - \definefontsynonym [SerifCaps] [StoneSerifSCITC-Medium] - % - \definefontsynonym[StoneSerifITC-Bold] [stosfb] - \definefontsynonym[StoneSerifITC-BoldItalic] [stosfbi] - \definefontsynonym[StoneSerifITC-Medium] [stosfm] - \definefontsynonym[StoneSerifITC-MediumItalic][stosfmi] - \definefontsynonym[StoneSerifSemITC-Semi] [stosfs] - \definefontsynonym[StoneSerifSemITC-SemiIta] [stosfsi] - \definefontsynonym[StoneSerifSCITC-Medium] [stosfscm] - \definefontsynonym[StoneSerifSemSCITC-Semi] [stosfscs] - % - \stoptypescript - - \starttypescript [sans] [stone-oldstyle] [name] - % - \definefontsynonym [Sans] [StoneSansOSITC-Medium] - \definefontsynonym [SansItalic] [StoneSansOSITC-MediumItalic] - \definefontsynonym [SansSlanted] [StoneSansOSITC-MediumItalic] - \definefontsynonym [SansBold] [StoneSansOSITC-Bold] - \definefontsynonym [SansBoldItalic] [StoneSansOSITC-BoldItalic] - \definefontsynonym [SansBoldSlanted][StoneSansOSITC-BoldItalic] - \definefontsynonym [SansCaps] [StoneSansSCITC-Medium] - % - \definefontsynonym[StoneSansOSITC-Bold] [stosnob] - \definefontsynonym[StoneSansOSITC-BoldItalic] [stosnobi] - \definefontsynonym[StoneSansOSITC-Medium] [stosnom] - \definefontsynonym[StoneSansOSITC-MediumItalic][stosnomi] - \definefontsynonym[StoneSansSemOSITC-Semi] [stosnos] - \definefontsynonym[StoneSansSemOSITC-SemiIta] [stosnosi] - % - \stoptypescript - - \starttypescript [serif] [stone-oldstyle] [name] - % - \definefontsynonym [Serif] [StoneSerifOSITC-Medium] - \definefontsynonym [SerifItalic] [StoneSerifOSITC-MediumItalic] - \definefontsynonym [SerifSlanted] [StoneSerifOSITC-MediumItalic] - \definefontsynonym [SerifBold] [StoneSerifOSITC-Bold] - \definefontsynonym [SerifBoldItalic] [StoneSerifOSITC-BoldItalic] - \definefontsynonym [SerifBoldSlanted] [StoneSerifOSITC-BoldItalic] - \definefontsynonym [SerifCaps] [StoneSerifSCITC-Medium] - % - \definefontsynonym[StoneSerifOSITC-Bold] [stosfob] - \definefontsynonym[StoneSerifOSITC-BoldItalic] [stosfobi] - \definefontsynonym[StoneSerifOSITC-Medium] [stosfom] - \definefontsynonym[StoneSerifOSITC-MediumItalic][stosfomi] - \definefontsynonym[StoneSerifSemOSITC-Semi] [stosfos] - \definefontsynonym[StoneSerifSemOSITC-SemiIta] [stosfosi] - % - \stoptypescript - -\stoptypescriptcollection - -% linotype industria - -\starttypescriptcollection[industria] - - \starttypescript [sans] [industria] [name] - \definefontsynonym[Industria-Solid][lt_50545] - \stoptypescript - -\stoptypescriptcollection diff --git a/tex/context/base/type-ini.lua b/tex/context/base/type-ini.lua index 4f53fbf40..9ee97acae 100644 --- a/tex/context/base/type-ini.lua +++ b/tex/context/base/type-ini.lua @@ -35,9 +35,7 @@ end local function failure_one(name) name_two = gsub(name,"%-.*$","") - if name == "loc" then - -- ignore - elseif name_two == name then + if name_two == name then report_typescripts("unknown library %a",name_one) else commands.uselibrary { diff --git a/tex/context/base/typo-bld.lua b/tex/context/base/typo-bld.lua index ad37c36f4..bc9f66ee4 100644 --- a/tex/context/base/typo-bld.lua +++ b/tex/context/base/typo-bld.lua @@ -6,12 +6,9 @@ if not modules then modules = { } end modules ['typo-bld'] = { -- was node-par license = "see context related readme files" } --- no need for nuts in the one-line demo (that might move anyway) - local insert, remove = table.insert, table.remove -builders = builders or { } -local builders = builders +local builders, nodes, node = builders, nodes, node builders.paragraphs = builders.paragraphs or { } local parbuilders = builders.paragraphs @@ -36,12 +33,11 @@ local texsetattribute = tex.setattribute local texnest = tex.nest local texlists = tex.lists -local nodes = nodes local nodepool = nodes.pool local new_baselineskip = nodepool.baselineskip local new_lineskip = nodepool.lineskip -local insert_node_before = nodes.insert_before -local hpack_node = nodes.hpack +local insert_node_before = node.insert_before +local hpack_node = node.hpack local starttiming = statistics.starttiming local stoptiming = statistics.stoptiming @@ -173,6 +169,7 @@ function constructors.disable() enabled = false end + callbacks.register('linebreak_filter', processor, "breaking paragraps into lines") statistics.register("linebreak processing time", function() @@ -229,16 +226,7 @@ local function report(groupcode,head) report_page_builder(" list : %s",head and nodeidstostring(head) or "<empty>") end --- use tex.[sg]etlist - function builders.buildpage_filter(groupcode) - -- -- this needs checking .. gets called too often - -- if group_code ~= "after_output" then - -- if trace_page_builder then - -- report(groupcode) - -- end - -- return nil, false - -- end local head, done = texlists.contrib_head, false if head then starttiming(builders) @@ -249,16 +237,14 @@ function builders.buildpage_filter(groupcode) stoptiming(builders) -- -- doesn't work here (not passed on?) -- tex.pagegoal = tex.vsize - tex.dimen.d_page_floats_inserted_top - tex.dimen.d_page_floats_inserted_bottom - texlists.contrib_head = head or nil -- needs checking --- tex.setlist("contrib_head",head,head and nodes.tail(head)) - return done and head or true -- no return value needed + texlists.contrib_head = head + return done and head or true else if trace_page_builder then report(groupcode) end - return nil, false -- no return value needed + return nil, false end - end callbacks.register('vpack_filter', builders.vpack_filter, "vertical spacing etc") diff --git a/tex/context/base/typo-brk.lua b/tex/context/base/typo-brk.lua index be11da9c3..3558efa8e 100644 --- a/tex/context/base/typo-brk.lua +++ b/tex/context/base/typo-brk.lua @@ -20,36 +20,19 @@ local report_breakpoints = logs.reporter("typesetting","breakpoints") local nodes, node = nodes, node local settings_to_array = utilities.parsers.settings_to_array +local copy_node = node.copy +local copy_nodelist = node.copy_list +local free_node = node.free +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local remove_node = nodes.remove -- ! nodes -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar -local getfont = nuts.getfont -local getid = nuts.getid -local getfield = nuts.getfield -local getattr = nuts.getattr - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local copy_node = nuts.copy -local copy_nodelist = nuts.copy_list -local free_node = nuts.free -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local remove_node = nuts.remove - -local tonodes = nuts.tonodes +local tonodes = nodes.tonodes local texsetattribute = tex.setattribute local unsetvalue = attributes.unsetvalue -local nodepool = nuts.pool +local nodepool = nodes.pool local tasks = nodes.tasks local v_reset = interfaces.variables.reset @@ -97,82 +80,74 @@ local function insert_break(head,start,before,after) end methods[1] = function(head,start) - if getprev(start) and getnext(start) then + if start.prev and start.next then insert_break(head,start,10000,0) end return head, start end methods[2] = function(head,start) -- ( => (- - if getprev(start) and getnext(start) then + if start.prev and start.next then local tmp head, start, tmp = remove_node(head,start) head, start = insert_node_before(head,start,new_disc()) - setfield(start,"attr",copy_nodelist(getfield(tmp,"attr"))) - setfield(start,"replace",tmp) - local tmp = copy_node(tmp) - local hyphen = copy_node(tmp) - setfield(hyphen,"char",languages.prehyphenchar(getfield(tmp,"lang"))) - setfield(tmp,"next",hyphen) - setfield(hyphen,"prev",tmp) - setfield(start,"post",tmp) + start.attr = copy_nodelist(tmp.attr) -- todo: critical only + start.replace = tmp + local tmp, hyphen = copy_node(tmp), copy_node(tmp) + hyphen.char = languages.prehyphenchar(tmp.lang) + tmp.next, hyphen.prev = hyphen, tmp + start.post = tmp insert_break(head,start,10000,10000) end return head, start end methods[3] = function(head,start) -- ) => -) - if getprev(start) and getnext(start) then + if start.prev and start.next then local tmp head, start, tmp = remove_node(head,start) head, start = insert_node_before(head,start,new_disc()) - setfield(start,"attr",copy_nodelist(getfield(tmp,"attr"))) - setfield(start,"replace",tmp) - local tmp = copy_node(tmp) - local hyphen = copy_node(tmp) - setfield(hyphen,"char",languages.prehyphenchar(getfield(tmp,"lang"))) - setfield(tmp,"prev",hyphen) - setfield(hyphen,"next",tmp) - setfield(start,"pre",hyphen) + start.attr = copy_nodelist(tmp.attr) -- todo: critical only + start.replace = tmp + local tmp, hyphen = copy_node(tmp), copy_node(tmp) + hyphen.char = languages.prehyphenchar(tmp.lang) + tmp.prev, hyphen.next = hyphen, tmp + start.pre = hyphen insert_break(head,start,10000,10000) end return head, start end methods[4] = function(head,start) -- - => - - - - if getprev(start) and getnext(start) then + if start.prev and start.next then local tmp head, start, tmp = remove_node(head,start) head, start = insert_node_before(head,start,new_disc()) - setfield(start,"attr",copy_nodelist(getfield(tmp,"attr"))) - setfield(start,"pre",copy_node(tmp)) - setfield(start,"post",copy_node(tmp)) - setfield(start,"replace",tmp) + start.attr = copy_nodelist(tmp.attr) -- todo: critical only + start.pre, start.post, start.replace = copy_node(tmp), copy_node(tmp), tmp insert_break(head,start,10000,10000) end return head, start end methods[5] = function(head,start,settings) -- x => p q r - if getprev(start) and getnext(start) then + if start.prev and start.next then local tmp head, start, tmp = remove_node(head,start) head, start = insert_node_before(head,start,new_disc()) - local attr = getfield(tmp,"attr") - local font = getfont(tmp) - local left = settings.left - local right = settings.right - local middle = settings.middle + local attr = tmp.attr + local font = tmp.font + start.attr = copy_nodelist(attr) -- todo: critical only + local left, right, middle = settings.left, settings.right, settings.middle if left then - setfield(start,"pre",(tonodes(tostring(left),font,attr))) -- was right + start.pre = tonodes(tostring(left),font,attr) -- was right end if right then - setfield(start,"post",(tonodes(tostring(right),font,attr))) -- was left + start.post = tonodes(tostring(right),font,attr) -- was left end if middle then - setfield(start,"replace",(tonodes(tostring(middle),font,attr))) + start.replace = tonodes(tostring(middle),font,attr) end - setfield(start,"attr",copy_nodelist(attr)) -- todo: critical only free_node(tmp) insert_break(head,start,10000,10000) end @@ -180,32 +155,31 @@ methods[5] = function(head,start,settings) -- x => p q r end function breakpoints.handler(head) - head = tonut(head) local done, numbers = false, languages.numbers local start, n = head, 0 while start do - local id = getid(start) + local id = start.id if id == glyph_code then - local attr = getattr(start,a_breakpoints) + local attr = start[a_breakpoints] if attr and attr > 0 then - setattr(start,a_breakpoints,unsetvalue) -- maybe test for subtype > 256 (faster) + start[a_breakpoints] = unsetvalue -- maybe test for subtype > 256 (faster) -- look ahead and back n chars local data = mapping[attr] if data then local map = data.characters - local cmap = map[getchar(start)] + local cmap = map[start.char] if cmap then - local lang = getfield(start,"lang") + local lang = start.lang -- we do a sanity check for language local smap = lang and lang >= 0 and lang < 0x7FFF and (cmap[numbers[lang]] or cmap[""]) if smap then if n >= smap.nleft then local m = smap.nright - local next = getnext(start) + local next = start.next while next do -- gamble on same attribute (not that important actually) - local id = getid(next) + local id = next.id if id == glyph_code then -- gamble on same attribute (not that important actually) - if map[getchar(next)] then + if map[next.char] then break elseif m == 1 then local method = methods[smap.type] @@ -216,10 +190,10 @@ function breakpoints.handler(head) break else m = m - 1 - next = getnext(next) + next = next.next end - elseif id == kern_code and getsubtype(next) == kerning_code then - next = getnext(next) + elseif id == kern_code and next.subtype == kerning_code then + next = next.next -- ignore intercharacter kerning, will go way else -- we can do clever and set n and jump ahead but ... not now @@ -240,14 +214,14 @@ function breakpoints.handler(head) else -- n = n + 1 -- if we want single char handling (|-|) then we will use grouping and then we need this end - elseif id == kern_code and getsubtype(start) == kerning_code then + elseif id == kern_code and start.subtype == kerning_code then -- ignore intercharacter kerning, will go way else n = 0 end - start = getnext(start) + start = start.next end - return tonode(head), done + return head, done end local enabled = false diff --git a/tex/context/base/typo-cap.lua b/tex/context/base/typo-cap.lua index 78ed8700a..0fc1a3093 100644 --- a/tex/context/base/typo-cap.lua +++ b/tex/context/base/typo-cap.lua @@ -16,23 +16,9 @@ local report_casing = logs.reporter("typesetting","casing") local nodes, node = nodes, node -local nuts = nodes.nuts -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar - -local copy_node = nuts.copy -local end_of_math = nuts.end_of_math +local copy_node = nodes.copy +local end_of_math = nodes.end_of_math + local nodecodes = nodes.nodecodes local skipcodes = nodes.skipcodes @@ -110,14 +96,14 @@ local lccodes = characters.lccodes -- true false true == mixed local function helper(start,attr,lastfont,n,codes,special,once,keepother) - local char = getchar(start) + local char = start.char local dc = codes[char] if dc then - local fnt = getfont(start) + local fnt = start.font if keepother and dc == char then local lfa = lastfont[n] if lfa then - setfield(start,"font",lfa) + start.font = lfa return start, true else return start, false @@ -126,10 +112,10 @@ local function helper(start,attr,lastfont,n,codes,special,once,keepother) if special then local lfa = lastfont[n] if lfa then - local previd = getid(getprev(start)) + local previd = start.prev.id if previd ~= glyph_code and previd ~= disc_code then fnt = lfa - setfield(start,"font",lfa) + start.font = lfa end end end @@ -151,18 +137,18 @@ local function helper(start,attr,lastfont,n,codes,special,once,keepother) local chr = dc[i] prev = start if i == 1 then - setfield(start,"char",chr) + start.char = chr else local g = copy_node(original) - setfield(g,"char",chr) - local next = getnext(start) - setfield(g,"prev",start) + g.char = chr + local next = start.next + g.prev = start if next then - setfield(g,"next",next) - setfield(start,"next",g) - setfield(next,"prev",g) + g.next = next + start.next = g + next.prev = g end - start = g + start = g end end if once then @@ -175,7 +161,7 @@ local function helper(start,attr,lastfont,n,codes,special,once,keepother) end return start, false elseif ifc[dc] then - setfield(start,"char",dc) + start.char = dc if once then lastfont[n] = false end @@ -217,29 +203,29 @@ local function word(start,attr,lastfont,n) end local function blockrest(start) - local n = getnext(start) + local n = start.next while n do - local id = getid(n) - if id == glyph_code or id == disc_node and getattr(n,a_cases) == attr then - setattr(n,a_cases,unsetvalue) + local id = n.id + if id == glyph_code or id == disc_node and n[a_cases] == attr then + n[a_cases] = unsetvalue else -- break -- we can have nested mess end - n = getnext(n) + n = n.next end end local function Word(start,attr,lastfont,n) -- looks quite complex lastfont[n] = false - local prev = getprev(start) - if prev and getid(prev) == kern_code and getsubtype(prev) == kerning_code then - prev = getprev(prev) + local prev = start.prev + if prev and prev.id == kern_code and prev.subtype == kerning_code then + prev = prev.prev end if not prev then blockrest(start) return helper(start,attr,lastfont,n,uccodes) end - local previd = getid(prev) + local previd = prev.id if previd ~= glyph_code and previd ~= disc_code then -- only the first character is treated blockrest(start) @@ -253,14 +239,14 @@ end local function Words(start,attr,lastfont,n) lastfont[n] = false - local prev = getprev(start) - if prev and getid(prev) == kern_code and getsubtype(prev) == kerning_code then - prev = getprev(prev) + local prev = start.prev + if prev and prev.id == kern_code and prev.subtype == kerning_code then + prev = prev.prev end if not prev then return helper(start,attr,lastfont,n,uccodes) end - local previd = getid(prev) + local previd = prev.id if previd ~= glyph_code and previd ~= disc_code then return helper(start,attr,lastfont,n,uccodes) else @@ -286,15 +272,15 @@ end local function random(start,attr,lastfont,n) lastfont[n] = false - local ch = getchar(start) - local tfm = fontchar[getfont(start)] + local ch = start.char + local tfm = fontchar[start.font] if lccodes[ch] then while true do local d = chardata[randomnumber(1,0xFFFF)] if d then local uc = uccodes[d] if uc and tfm[uc] then -- this also intercepts tables - setfield(start,"char",uc) + start.char = uc return start, true end end @@ -305,7 +291,7 @@ local function random(start,attr,lastfont,n) if d then local lc = lccodes[d] if lc and tfm[lc] then -- this also intercepts tables - setfield(start,"char",lc) + start.char = lc return start, true end end @@ -328,20 +314,19 @@ register(variables.cap, variables.capital) -- clone register(variables.Cap, variables.Capital) -- clone function cases.handler(head) -- not real fast but also not used on much data - head = tonut(head) local lastfont = { } local lastattr = nil local done = false local start = head while start do -- while because start can jump ahead - local id = getid(start) + local id = start.id if id == glyph_code then - local attr = getattr(start,a_cases) + local attr = start[a_cases] if attr and attr > 0 then if attr ~= lastattr then lastattr = attr end - setattr(start,a_cases,unsetvalue) + start[a_cases] = unsetvalue local n, id, m = get(attr) if lastfont[n] == nil then lastfont[n] = id @@ -360,27 +345,27 @@ function cases.handler(head) -- not real fast but also not used on much data end end elseif id == disc_code then - local attr = getattr(start,a_cases) + local attr = start[a_cases] if attr and attr > 0 then if attr ~= lastattr then lastattr = attr end - setattr(start,a_cases,unsetvalue) + start[a_cases] = unsetvalue local n, id, m = get(attr) if lastfont[n] == nil then lastfont[n] = id end local action = actions[n] -- map back to low number if action then - local replace = getfield(start,"replace") + local replace = start.replace if replace then action(replace,attr,lastfont,n) end - local pre = getfield(start,"pre") + local pre = start.pre if pre then action(pre,attr,lastfont,n) end - local post = getfield(start,"post") + local post = start.post if post then action(post,attr,lastfont,n) end @@ -390,10 +375,10 @@ function cases.handler(head) -- not real fast but also not used on much data start = end_of_math(start) end if start then -- why test - start = getnext(start) + start = start.next end end - return tonode(head), done + return head, done end local enabled = false diff --git a/tex/context/base/typo-cln.lua b/tex/context/base/typo-cln.lua index b7e337662..2aa05b6d1 100644 --- a/tex/context/base/typo-cln.lua +++ b/tex/context/base/typo-cln.lua @@ -28,14 +28,7 @@ local tasks = nodes.tasks local texsetattribute = tex.setattribute -local nuts = nodes.nuts -local tonut = nuts.tonut - -local setfield = nuts.setfield -local getchar = nuts.getchar -local getattr = nuts.getattr - -local traverse_id = nuts.traverse_id +local traverse_id = node.traverse_id local unsetvalue = attributes.unsetvalue @@ -55,18 +48,18 @@ local resetter = { -- this will become an entry in char-def function cleaners.handler(head) local inline, done = false, false - for n in traverse_id(glyph_code,tonut(head)) do - local char = getchar(n) + for n in traverse_id(glyph_code,head) do + local char = n.char if resetter[char] then inline = false elseif not inline then - local a = getattr(n,a_cleaner) + local a = n[a_cleaner] if a == 1 then -- currently only one cleaner so no need to be fancy local upper = uccodes[char] if type(upper) == "table" then -- some day, not much change that \SS ends up here else - setfield(n,"char",upper) + n.char = upper done = true if trace_autocase then report_autocase("") diff --git a/tex/context/base/typo-dha.lua b/tex/context/base/typo-dha.lua index 15e345ff8..d5ad66e7e 100644 --- a/tex/context/base/typo-dha.lua +++ b/tex/context/base/typo-dha.lua @@ -49,30 +49,13 @@ local trace_directions = false trackers.register("typesetters.directions.defa local report_directions = logs.reporter("typesetting","text directions") -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode -local nutstring = nuts.tostring - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getfont = nuts.getfont -local getchar = nuts.getchar -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getfield = nuts.getfield -local setfield = nuts.setfield -local getattr = nuts.getattr -local setattr = nuts.setattr - -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local remove_node = nuts.remove -local end_of_math = nuts.end_of_math - - -local nodepool = nuts.pool + +local insert_node_before = nodes.insert_before +local insert_node_after = nodes.insert_after +local remove_node = nodes.remove +local end_of_math = nodes.end_of_math + +local nodepool = nodes.pool local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes @@ -125,7 +108,7 @@ end local function process(start) - local head = tonut(start) -- we have a global head + local head = start local current = head local inserted = nil @@ -197,31 +180,31 @@ local function process(start) end local function nextisright(current) - current = getnext(current) - local id = getid(current) + current = current.next + local id = current.id if id == glyph_code then - local character = getchar(current) + local character = current.char local direction = chardirections[character] return direction == "r" or direction == "al" or direction == "an" end end local function previsright(current) - current = getprev(current) - local id = getid(current) + current = current.prev + local id = current.id if id == glyph_code then - local character = getchar(current) + local char = current.char local direction = chardirections[character] return direction == "r" or direction == "al" or direction == "an" end end while current do - local id = getid(current) + local id = current.id if id == math_code then - current = getnext(end_of_math(getnext(current))) + current = end_of_math(current.next).next else - local attr = getattr(current,a_directions) + local attr = current[a_directions] if attr and attr > 0 and attr ~= prevattr then if not getglobal(a) then lro, rlo = false, false @@ -230,7 +213,7 @@ local function process(start) end if id == glyph_code then if attr and attr > 0 then - local character = getchar(current) + local character = current.char local direction = chardirections[character] local reversed = false if rlo or override > 0 then @@ -240,24 +223,24 @@ local function process(start) end elseif lro or override < 0 then if direction == "r" or direction == "al" then - setattr(current,a_state,s_isol) + current[a_state] = s_isol direction = "l" reversed = true end end if direction == "on" then local mirror = charmirrors[character] - if mirror and fontchar[getfont(current)][mirror] then + if mirror and fontchar[current.font][mirror] then local class = charclasses[character] if class == "open" then if nextisright(current) then if autodir >= 0 then force_auto_right_before(direction) end - setfield(current,"char",mirror) + current.char = mirror done = true elseif autodir < 0 then - setfield(current,"char",mirror) + current.char = mirror done = true else mirror = false @@ -268,14 +251,14 @@ local function process(start) local fencedir = fences[#fences] fences[#fences] = nil if fencedir < 0 then - setfield(current,"char",mirror) + current.char = mirror done = true force_auto_right_before(direction) else mirror = false end elseif autodir < 0 then - setfield(current,"char",mirror) + current.char = mirror done = true else mirror = false @@ -353,9 +336,9 @@ local function process(start) -- we do nothing end elseif id == whatsit_code then - local subtype = getsubtype(current) + local subtype = current.subtype if subtype == localpar_code then - local dir = getfield(current,"dir") + local dir = current.dir if dir == 'TRT' then autodir = -1 elseif dir == 'TLT' then @@ -368,7 +351,7 @@ local function process(start) if finish then finish_auto_before() end - local dir = getfield(current,"dir") + local dir = current.dir if dir == "+TRT" then finish, autodir = "TRT", -1 elseif dir == "-TRT" then @@ -387,7 +370,7 @@ local function process(start) elseif finish then finish_auto_before() end - local cn = getnext(current) + local cn = current.next if cn then -- we're okay elseif finish then @@ -407,7 +390,7 @@ local function process(start) end end - return tonode(head), done + return head, done end diff --git a/tex/context/base/typo-dig.lua b/tex/context/base/typo-dig.lua index 67849c6d4..ef05e62da 100644 --- a/tex/context/base/typo-dig.lua +++ b/tex/context/base/typo-dig.lua @@ -19,24 +19,10 @@ local report_digits = logs.reporter("typesetting","digits") local nodes, node = nodes, node -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getfont = nuts.getfont -local getchar = nuts.getchar -local getid = nuts.getid -local getfield = nuts.getfield -local setfield = nuts.setfield -local getattr = nuts.getattr -local setattr = nuts.setattr - -local hpack_node = nuts.hpack -local traverse_id = nuts.traverse_id -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after +local hpack_node = node.hpack +local traverse_id = node.traverse_id +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after local texsetattribute = tex.setattribute local unsetvalue = attributes.unsetvalue @@ -44,7 +30,7 @@ local unsetvalue = attributes.unsetvalue local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph -local nodepool = nuts.pool +local nodepool = nodes.pool local tasks = nodes.tasks local new_glue = nodepool.glue @@ -80,20 +66,16 @@ function nodes.aligned(head,start,stop,width,how) if how == "flushleft" or how == "middle" then head, stop = insert_node_after(head,stop,new_glue(0,65536,65536)) end - local prv = getprev(start) - local nxt = getnext(stop) - setfield(start,"prev",nil) - setfield(stop,"next",nil) + local prv, nxt = start.prev, stop.next + start.prev, stop.next = nil, nil local packed = hpack_node(start,width,"exactly") -- no directional mess here, just lr if prv then - setfield(prv,"next",packed) - setfield(packed,"prev",prv) + prv.next, packed.prev = packed, prv end if nxt then - setfield(nxt,"prev",packed) - setfield(packed,"next",nxt) + nxt.prev, packed.next = packed, nxt end - if getprev(packed) then + if packed.prev then return head, packed else return packed, packed @@ -101,13 +83,12 @@ function nodes.aligned(head,start,stop,width,how) end actions[1] = function(head,start,attr) - local font = getfont(start) - local char = getchar(start) + local font = start.font + local char = start.char local unic = chardata[font][char].tounicode local what = unic and tonumber(unic,16) or char if charbase[what].category == "nd" then - local oldwidth = getfield(start,"width") - local newwidth = getdigitwidth(font) + local oldwidth, newwidth = start.width, getdigitwidth(font) if newwidth ~= oldwidth then if trace_digits then report_digits("digit trigger %a, instance %a, char %C, unicode %U, delta %s", @@ -121,13 +102,12 @@ actions[1] = function(head,start,attr) end function digits.handler(head) - head = tonut(head) local done, current, ok = false, head, false while current do - if getid(current) == glyph_code then - local attr = getattr(current,a_digits) + if current.id == glyph_code then + local attr = current[a_digits] if attr and attr > 0 then - setattr(current,a_digits,unsetvalue) + current[a_digits] = unsetvalue local action = actions[attr%100] -- map back to low number if action then head, current, ok = action(head,current,attr) @@ -137,11 +117,9 @@ function digits.handler(head) end end end - if current then - current = getnext(current) - end + current = current and current.next end - return tonode(head), done + return head, done end local m, enabled = 0, false -- a trick to make neighbouring ranges work diff --git a/tex/context/base/typo-dir.lua b/tex/context/base/typo-dir.lua index fbca0f024..a04028452 100644 --- a/tex/context/base/typo-dir.lua +++ b/tex/context/base/typo-dir.lua @@ -40,35 +40,21 @@ local trace_directions = false trackers.register("typesetters.directions", local report_textdirections = logs.reporter("typesetting","text directions") local report_mathdirections = logs.reporter("typesetting","math directions") -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode -local nutstring = nuts.tostring - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getfont = nuts.getfont -local getchar = nuts.getchar -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getfield = nuts.getfield -local setfield = nuts.setfield -local getattr = nuts.getattr -local setattr = nuts.setattr -local hasbit = number.hasbit -local traverse_id = nuts.traverse_id -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local remove_node = nuts.remove -local end_of_math = nuts.end_of_math + +local traverse_id = node.traverse_id +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local remove_node = nodes.remove +local end_of_math = nodes.end_of_math local texsetattribute = tex.setattribute local texsetcount = tex.setcount local unsetvalue = attributes.unsetvalue +local hasbit = number.hasbit + local nodecodes = nodes.nodecodes local whatcodes = nodes.whatcodes local mathcodes = nodes.mathcodes @@ -90,7 +76,7 @@ local vlist_code = nodecodes.vlist local localpar_code = whatcodes.localpar local dir_code = whatcodes.dir -local nodepool = nuts.pool +local nodepool = nodes.pool local new_textdir = nodepool.textdir diff --git a/tex/context/base/typo-drp.lua b/tex/context/base/typo-drp.lua index 3a87d94b3..903140dae 100644 --- a/tex/context/base/typo-drp.lua +++ b/tex/context/base/typo-drp.lua @@ -11,7 +11,9 @@ if not modules then modules = { } end modules ['typo-drp'] = { local tonumber, type, next = tonumber, type, next local ceil = math.ceil -local settings_to_hash = utilities.parsers.settings_to_hash + +local utfbyte = utf.byte +local utfchar = utf.char local trace_initials = false trackers.register("typesetters.initials", function(v) trace_initials = v end) local report_initials = logs.reporter("nodes","initials") @@ -22,42 +24,19 @@ typesetters.initials = initials or { } local nodes = nodes local tasks = nodes.tasks -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getchar = nuts.getchar -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getfield = nuts.getfield -local getattr = nuts.getattr - -local setfield = nuts.setfield -local setattr = nuts.setattr - -local hpack_nodes = nuts.hpack - +local hpack_nodes = nodes.hpack local nodecodes = nodes.nodecodes local whatsitcodes = nodes.whatsitcodes -local nodepool = nuts.pool +local nodepool = nodes.pool local new_kern = nodepool.kern -local insert_before = nuts.insert_before -local insert_after = nuts.insert_after -local remove_node = nuts.remove -local traverse_id = nuts.traverse_id -local traverse = nuts.traverse -local free_node = nuts.free +local insert_before = nodes.insert_before +local insert_after = nodes.insert_after local variables = interfaces.variables local v_default = variables.default local v_margin = variables.margin -local v_auto = variables.auto -local v_first = variables.first -local v_last = variables.last local texget = tex.get local texsetattribute = tex.setattribute @@ -65,8 +44,7 @@ local unsetvalue = attributes.unsetvalue local glyph_code = nodecodes.glyph local hlist_code = nodecodes.hlist -local glue_code = nodecodes.glue -local kern_code = nodecodes.kern +local kern_node = nodecodes.kern local whatsit_code = nodecodes.whatsit local localpar_code = whatsitcodes.localpar @@ -78,8 +56,6 @@ local a_color = attributes.private('color') local a_transparency = attributes.private('transparency') local a_colorspace = attributes.private('colormodel') -local category = characters.category - local settings = nil function initials.set(specification) @@ -108,288 +84,74 @@ commands.setinitial = initials.set -- todo: prevent linebreak .. but normally a initial ends up at the top of -- a page so this has a low priority --- actions[v_default] = function(head,setting) --- local done = false --- if getid(head) == whatsit_code and getsubtype(head) == localpar_code then --- -- begin of par --- local first = getnext(head) --- -- parbox .. needs to be set at 0 --- if first and getid(first) == hlist_code then --- first = getnext(first) --- end --- -- we need to skip over kerns and glues (signals) --- while first and getid(first) ~= glyph_code do --- first = getnext(first) --- end --- if first and getid(first) == glyph_code then --- local char = getchar(first) --- local prev = getprev(first) --- local next = getnext(first) --- -- if getid(prev) == hlist_code then --- -- -- set the width to 0 --- -- end --- if next and getid(next) == kern_code then --- setfield(next,"kern",0) --- end --- if setting.font then --- setfield(first,"font",setting.font) --- end --- if setting.dynamic > 0 then --- setattr(first,0,setting.dynamic) --- end --- -- can be a helper --- local ma = setting.ma or 0 --- local ca = setting.ca --- local ta = setting.ta --- if ca and ca > 0 then --- setattr(first,a_colorspace,ma == 0 and 1 or ma) --- setattr(first,a_color,ca) --- end --- if ta and ta > 0 then --- setattr(first,a_transparency,ta) --- end --- -- --- local width = getfield(first,"width") --- local height = getfield(first,"height") --- local depth = getfield(first,"depth") --- local distance = setting.distance or 0 --- local voffset = setting.voffset or 0 --- local hoffset = setting.hoffset or 0 --- local parindent = tex.parindent --- local baseline = texget("baselineskip").width --- local lines = tonumber(setting.n) or 0 --- -- --- setfield(first,"xoffset",- width - hoffset - distance - parindent) --- setfield(first,"yoffset",- voffset) -- no longer - height here --- -- We pack so that successive handling cannot touch the dropped cap. Packaging --- -- in a hlist is also needed because we cannot locally adapt e.g. parindent (not --- -- yet stored in with localpar). --- setfield(first,"prev",nil) --- setfield(first,"next",nil) --- local h = hpack_nodes(first) --- setfield(h,"width",0) --- setfield(h,"height",0) --- setfield(h,"depth",0) --- setfield(prev,"next",h) --- setfield(next,"prev",h) --- setfield(h,"next",next) --- setfield(h,"prev",prev) --- first = h --- -- end of packaging --- if setting.location == v_margin then --- -- okay --- else --- if lines == 0 then -- safeguard, not too precise --- lines = ceil((height+voffset) / baseline) --- end --- -- We cannot set parshape yet ... when we can I'll add a slope --- -- option (positive and negative, in emwidth). --- local hangafter = - lines --- local hangindent = width + distance + parindent --- if trace_initials then --- report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent) --- end --- tex.hangafter = hangafter --- tex.hangindent = hangindent --- if parindent ~= 0 then --- insert_after(first,first,new_kern(-parindent)) --- end --- end --- done = true --- end --- end --- return head, done --- end - actions[v_default] = function(head,setting) local done = false - if getid(head) == whatsit_code and getsubtype(head) == localpar_code then + if head.id == whatsit_code and head.subtype == localpar_code then -- begin of par - local first = getnext(head) - local indent = false + local first = head.next -- parbox .. needs to be set at 0 - if first and getid(first) == hlist_code then - first = getnext(first) - indent = true + if first and first.id == hlist_code then + first = first.next end -- we need to skip over kerns and glues (signals) - while first and getid(first) ~= glyph_code do - first = getnext(first) + while first and first.id ~= glyph_code do + first = first.next end - if first and getid(first) == glyph_code then - local ma = setting.ma or 0 - local ca = setting.ca - local ta = setting.ta - local last = first + if first and first.id == glyph_code then + local char = first.char + local prev = first.prev + local next = first.next + -- if prev.id == hlist_code then + -- -- set the width to 0 + -- end + if next and next.id == kern_node then + next.kern = 0 + end + if setting.font then + first.font = setting.font + end + if setting.dynamic > 0 then + first[0] = setting.dynamic + end + -- can be a helper + local ma = setting.ma or 0 + local ca = setting.ca + local ta = setting.ta + if ca and ca > 0 then + first[a_colorspace] = ma == 0 and 1 or ma + first[a_color] = ca + end + if ta and ta > 0 then + first[a_transparency] = ta + end + -- + local width = first.width + local height = first.height + local depth = first.depth local distance = setting.distance or 0 local voffset = setting.voffset or 0 local hoffset = setting.hoffset or 0 local parindent = tex.parindent local baseline = texget("baselineskip").width local lines = tonumber(setting.n) or 0 - local dynamic = setting.dynamic - local font = setting.font - local method = settings_to_hash(setting.method) - local length = tonumber(setting.m) or 1 - -- - -- 1 char | n chars | skip first quote | ignore punct | keep punct -- - if getattr(first,a_initial) then - for current in traverse(getnext(first)) do - if getattr(current,a_initial) then - last = current - else - break - end - end - elseif method[v_auto] then - local char = getchar(first) - local kind = category(char) - if kind == "po" or kind == "pi" then - if method[v_first] then - -- remove quote etc before initial - local next = getnext(first) - if not next then - -- don't start with a quote or so - return head, false - end - last = nil - for current in traverse_id(glyph_code,next) do - head, first = remove_node(head,first,true) - first = current - last = first - break - end - if not last then - -- no following glyph or so - return head, false - end - else - -- keep quote etc with initial - local next = getnext(first) - if not next then - -- don't start with a quote or so - return head, false - end - for current in traverse_id(glyph_code,next) do - last = current - break - end - if last == first then - return head, false - end - end - elseif kind == "pf" then - -- error: final quote - else - -- okay - end - -- maybe also: get all A. B. etc - local next = getnext(first) - if next then - for current in traverse_id(glyph_code,next) do - local char = getchar(current) - local kind = category(char) - if kind == "po" then - if method[v_last] then - -- remove period etc after initial - remove_node(head,current,true) - else - -- keep period etc with initial - last = current - end - end - break - end - end - else - for current in traverse_id(glyph_code,first) do - last = current - if length <= 1 then - break - else - length = length - 1 - end - end - end - local current = first - while true do - local id = getid(current) - if id == kern_code then - setfield(current,"kern",0) - elseif id == glyph_code then - local next = getnext(current) - if font then - setfield(current,"font",font) - end - if dynamic > 0 then - setattr(current,0,dynamic) - end - -- can be a helper - if ca and ca > 0 then - setattr(current,a_colorspace,ma == 0 and 1 or ma) - setattr(current,a_color,ca) - end - if ta and ta > 0 then - setattr(current,a_transparency,ta) - end - -- - end - if current == last then - break - else - current = getnext(current) - end - end + first.xoffset = - width - hoffset - distance - parindent + first.yoffset = - voffset -- no longer - height here -- We pack so that successive handling cannot touch the dropped cap. Packaging -- in a hlist is also needed because we cannot locally adapt e.g. parindent (not -- yet stored in with localpar). - local prev = getprev(first) - local next = getnext(last) - -- - setfield(first,"prev",nil) - setfield(last,"next",nil) - local dropper = hpack_nodes(first) - local width = getfield(dropper,"width") - local height = getfield(dropper,"height") - local depth = getfield(dropper,"depth") - setfield(dropper,"width",0) - setfield(dropper,"height",0) - setfield(dropper,"depth",0) - -- - setfield(prev,"next",dropper) - if next then - setfield(next,"prev",dropper) - end - setfield(dropper,"next",next) - setfield(dropper,"prev",prev) - -- - if next then - local current = next - while current do - local id = getid(current) - if id == glue_code or id == kern_code then - local next = getnext(current) - -- remove_node(current,current,true) -- created an invalid next link and dangling remains - remove_node(head,current,true) - current = next - else - break - end - end - end - -- - local hoffset = width + hoffset + distance + (indent and parindent or 0) - for current in traverse_id(glyph_code,first) do - setfield(current,"xoffset",- hoffset ) - setfield(current,"yoffset",- voffset) -- no longer - height here - if current == last then - break - end - end - -- - first = dropper - -- + first.prev = nil + first.next = nil + local h = hpack_nodes(first) + h.width = 0 + h.height = 0 + h.depth = 0 + prev.next = h + next.prev = h + h.next = next + h.prev = prev + + -- end of packaging if setting.location == v_margin then -- okay else @@ -399,15 +161,15 @@ actions[v_default] = function(head,setting) -- We cannot set parshape yet ... when we can I'll add a slope -- option (positive and negative, in emwidth). local hangafter = - lines - local hangindent = width + distance + local hangindent = width + distance + parindent if trace_initials then report_initials("setting hangafter to %i and hangindent to %p",hangafter,hangindent) end tex.hangafter = hangafter tex.hangindent = hangindent - end - if indent then - insert_after(first,first,new_kern(-parindent)) + if parindent ~= 0 then + insert_after(first,first,new_kern(-parindent)) + end end done = true end @@ -416,17 +178,16 @@ actions[v_default] = function(head,setting) end function initials.handler(head) - head = tonut(head) local start = head local attr = nil while start do - attr = getattr(start,a_initial) + attr = start[a_initial] if attr then break - elseif getid(start) == glyph then + elseif start.id == glyph then break else - start = getnext(start) + start = start.next end end if attr then @@ -440,8 +201,8 @@ function initials.handler(head) report_initials("processing initials, alternative %a",alternative) end local head, done = action(head,settings) - return tonode(head), done + return head, done end end - return tonode(head), false + return head, false end diff --git a/tex/context/base/typo-drp.mkiv b/tex/context/base/typo-drp.mkiv index 3ac47466f..78f6df0a2 100644 --- a/tex/context/base/typo-drp.mkiv +++ b/tex/context/base/typo-drp.mkiv @@ -57,8 +57,6 @@ \setupinitial [\c!location=\v!text, \c!n=3, - \c!m=1, - \c!method=\v!none, % \s!font=Bold sa 4, % \s!font=Bold ht \measure{initial:n}, \s!font=Bold cp \measure{initial:n}, @@ -69,25 +67,24 @@ \c!color=, \c!before=\blank] -\unexpanded\def\placeinitial % we cannot group so no settings +\unexpanded\def\placeinitial {\dosingleempty\typo_initials_place} \def\typo_initials_place[#1]% old command {\par \namedinitialparameter{#1}\c!before - \setinitial[#1]\relax} + \setinitial[#1]} \unexpanded\def\setinitial - {\dodoubleempty\typo_initials_set} + {\dosingleempty\typo_initials_set} -\unexpanded\def\typo_initials_set[#1][#2]% - {\edef\typo_initial_handle{\typo_initial_handle_indeed{#1}{#2}}} +\unexpanded\def\typo_initials_set[#1]% + {\edef\typo_initial_handle{\typo_initial_handle_indeed{#1}}} -\unexpanded\def\typo_initial_handle_indeed#1#2% +\unexpanded\def\typo_initial_handle_indeed#1% {\dontleavehmode \begingroup \edef\currentinitial{#1}% - \setupcurrentinitial[#2]% \scratchcounter \initialparameter\c!n\relax \scratchdistance\initialparameter\c!distance\relax \scratchhoffset \initialparameter\c!hoffset \relax @@ -98,43 +95,24 @@ {\definedfont[\initialparameter\s!font]} {\useinitialstyleparameter\c!style}% \useinitialcolorparameter\c!color - \edef\p_text{\initialparameter\c!text}% optional \ctxcommand{setinitial{ - location = "\initialparameter\c!location", - enabled = true, - n = \number\scratchcounter, - m = \number\initialparameter\c!m, - method = "\initialparameter\c!method", - distance = \number\scratchdistance, - hoffset = \number\scratchhoffset, - voffset = \number\scratchvoffset, - ma = \the\attribute\colormodelattribute, - ca = \the\attribute\colorattribute, - ta = \the\attribute\transparencyattribute, - font = \fontid\font, - dynamic = \number\attribute\zerocount, % it's a bit over the top to support this here + location = "\initialparameter\c!location", + enabled = true, + n = \number\scratchcounter, + distance = \number\scratchdistance, + hoffset = \number\scratchhoffset, + voffset = \number\scratchvoffset, + ma = \the\attribute\colormodelattribute , + ca = \the\attribute\colorattribute , + ta = \the\attribute\transparencyattribute, + font = \fontid\font, + dynamic = \number\attribute\zerocount, % it's a bit over the top to support this here }}% \stopluacode \kern\zeropoint % we need a node - \p_text \endgroup \globallet\typo_initial_handle\relax} \let\typo_initial_handle\relax -% \setupbodyfont[dejavu,9pt] -% -% \startbuffer -% \setinitial[two] D. E. Knuth \ignorespaces\input knuth \par -% \setinitial[two] Knuth \ignorespaces\input knuth \par -% \setinitial[two] \quotation{D. E. Knuth} \ignorespaces\input knuth \par -% \setinitial[two] \quotation {Knuth} \ignorespaces\input knuth \par -% \setinitial[two] [text={D.E. Knuth}] \ignorespaces\input knuth \par -% \setinitial[two] [m=4] D. E. Knuth \ignorespaces\input knuth \par -% \stopbuffer -% -% \type{m=2} \start \defineinitial[two][m=2,method=none] \getbuffer \page \stop -% \type{m=1,method=auto} \start \defineinitial[two][m=1,method=auto] \getbuffer \page \stop -% \type{m=1,method={auto,first,last}} \start \defineinitial[two][m=1,method={first,auto,last}] \getbuffer \page \stop - \protect \endinput diff --git a/tex/context/base/typo-dua.lua b/tex/context/base/typo-dua.lua index 91a27a30e..ec85a3d9f 100644 --- a/tex/context/base/typo-dua.lua +++ b/tex/context/base/typo-dua.lua @@ -66,24 +66,11 @@ local formatters = string.formatters local directiondata = characters.directions local mirrordata = characters.mirrors -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode -local nutstring = nuts.tostring - -local getnext = nuts.getnext -local getchar = nuts.getchar -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getfield = nuts.getfield -local setfield = nuts.setfield - -local remove_node = nuts.remove -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before - -local nodepool = nuts.pool +local remove_node = nodes.remove +local insert_node_after = nodes.insert_after +local insert_node_before = nodes.insert_before + +local nodepool = nodes.pool local new_textdir = nodepool.textdir local nodecodes = nodes.nodecodes @@ -202,17 +189,17 @@ local function build_list(head) -- todo: store node pointer ... saves loop local size = 0 while current do size = size + 1 - local id = getid(current) + local id = current.id if id == glyph_code then - local chr = getchar(current) + local chr = current.char local dir = directiondata[chr] list[size] = { char = chr, direction = dir, original = dir, level = 0 } - current = getnext(current) + current = current.next elseif id == glue_code then list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 } - current = getnext(current) - elseif id == whatsit_code and getsubtype(current) == dir_code then - local dir = getfield(current,"dir") + current = current.next + elseif id == whatsit_code and current.subtype == dir_code then + local dir = current.dir if dir == "+TLT" then list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 } elseif dir == "+TRT" then @@ -222,27 +209,27 @@ local function build_list(head) -- todo: store node pointer ... saves loop else list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character end - current = getnext(current) + current = current.next elseif id == math_code then local skip = 0 - current = getnext(current) - while getid(current) ~= math_code do + current = current.next + while current.id ~= math_code do skip = skip + 1 - current = getnext(current) + current = current.next end - skip = skip + 1 - current = getnext(current) + skip = skip + 1 + current = current.next list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id } else local skip = 0 local last = id - current = getnext(current) + current = current.next while n do - local id = getid(current) - if id ~= glyph_code and id ~= glue_code and not (id == whatsit_code and getsubtype(current) == dir_code) then + local id = current.id + if id ~= glyph_code and id ~= glue_code and not (id == whatsit_code and current.subtype == dir_code) then skip = skip + 1 last = id - current = getnext(current) + current = current.next else break end @@ -302,8 +289,8 @@ local function find_run_limit_b_s_ws_on(list,start,limit) end local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for local_par) - if getid(head) == whatsit_code and getsubtype(head) == localpar_code then - if getfield(head,"dir") == "TRT" then + if head.id == whatsit_code and head.subtype == localpar_code then + if head.dir == "TRT" then return 1, "TRT", true else return 0, "TLT", true @@ -690,30 +677,30 @@ local function apply_to_list(list,size,head,pardir) report_directions("fatal error, size mismatch") break end - local id = getid(current) + local id = current.id local entry = list[index] local begindir = entry.begindir local enddir = entry.enddir if id == glyph_code then local mirror = entry.mirror if mirror then - setfield(current,"char",mirror) + current.char = mirror end if trace_directions then local direction = entry.direction setcolor(current,direction,direction ~= entry.original,mirror) end elseif id == hlist_code or id == vlist_code then - setfield(current,"dir",pardir) -- is this really needed? + current.dir = pardir -- is this really needed? elseif id == glue_code then - if enddir and getsubtype(current) == parfillskip_code then + if enddir and current.subtype == parfillskip_code then -- insert the last enddir before \parfillskip glue head = insert_node_before(head,current,new_textdir(enddir)) enddir = false done = true end elseif id == whatsit_code then - if begindir and getsubtype(current) == localpar_code then + if begindir and current.subtype == localpar_code then -- local_par should always be the 1st node head, current = insert_node_after(head,current,new_textdir(begindir)) begindir = nil @@ -727,7 +714,7 @@ local function apply_to_list(list,size,head,pardir) local skip = entry.skip if skip and skip > 0 then for i=1,skip do - current = getnext(current) + current = current.next end end if enddir then @@ -735,13 +722,13 @@ local function apply_to_list(list,size,head,pardir) done = true end if not entry.remove then - current = getnext(current) + current = current.next elseif remove_controls then -- X9 head, current = remove_node(head,current,true) done = true else - current = getnext(current) + current = current.next end index = index + 1 end @@ -749,7 +736,6 @@ local function apply_to_list(list,size,head,pardir) end local function process(head) - head = tonut(head) local list, size = build_list(head) local baselevel, pardir, dirfound = get_baselevel(head,list,size) -- we always have an inline dir node in context if not dirfound and trace_details then @@ -766,7 +752,7 @@ local function process(head) report_directions("result : %s",show_done(list,size)) end head, done = apply_to_list(list,size,head,pardir) - return tonode(head), done + return head, done end directions.installhandler(interfaces.variables.one,process) diff --git a/tex/context/base/typo-dub.lua b/tex/context/base/typo-dub.lua index 4dc0f21fb..3ecfce364 100644 --- a/tex/context/base/typo-dub.lua +++ b/tex/context/base/typo-dub.lua @@ -54,25 +54,11 @@ local directiondata = characters.directions local mirrordata = characters.mirrors local textclassdata = characters.textclasses -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode -local nutstring = nuts.tostring - -local getnext = nuts.getnext -local getchar = nuts.getchar -local getid = nuts.getid -local getsubtype = nuts.getsubtype -local getlist = nuts.getlist -local getattr = nuts.getattr -local getfield = nuts.getfield -local setfield = nuts.setfield - -local remove_node = nuts.remove -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before - -local nodepool = nuts.pool +local remove_node = nodes.remove +local insert_node_after = nodes.insert_after +local insert_node_before = nodes.insert_before + +local nodepool = nodes.pool local new_textdir = nodepool.textdir local nodecodes = nodes.nodecodes @@ -256,17 +242,17 @@ local function build_list(head) -- todo: store node pointer ... saves loop local size = 0 while current do size = size + 1 - local id = getid(current) + local id = current.id if id == glyph_code then - local chr = getchar(current) + local chr = current.char local dir = directiondata[chr] list[size] = { char = chr, direction = dir, original = dir, level = 0 } - current = getnext(current) + current = current.next elseif id == glue_code then list[size] = { char = 0x0020, direction = "ws", original = "ws", level = 0 } - current = getnext(current) - elseif id == whatsit_code and getsubtype(current) == dir_code then - local dir = getfield(current,"dir") + current = current.next + elseif id == whatsit_code and current.subtype == dir_code then + local dir = current.dir if dir == "+TLT" then list[size] = { char = 0x202A, direction = "lre", original = "lre", level = 0 } elseif dir == "+TRT" then @@ -276,27 +262,27 @@ local function build_list(head) -- todo: store node pointer ... saves loop else list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, id = id } -- object replacement character end - current = getnext(current) + current = current.next elseif id == math_code then local skip = 0 - current = getnext(current) - while getid(current) ~= math_code do + current = current.next + while current.id ~= math_code do skip = skip + 1 - current = getnext(current) + current = current.next end skip = skip + 1 - current = getnext(current) + current = current.next list[size] = { char = 0xFFFC, direction = "on", original = "on", level = 0, skip = skip, id = id } else local skip = 0 local last = id - current = getnext(current) + current = current.next while n do - local id = getid(current) - if id ~= glyph_code and id ~= glue_code and not (id == whatsit_code and getsubtype(current) == dir_code) then + local id = current.id + if id ~= glyph_code and id ~= glue_code and not (id == whatsit_code and current.subtype == dir_code) then skip = skip + 1 last = id - current = getnext(current) + current = current.next else break end @@ -379,8 +365,8 @@ end -- the action local function get_baselevel(head,list,size) -- todo: skip if first is object (or pass head and test for local_par) - if getid(head) == whatsit_code and getsubtype(head) == localpar_code then - if getfield(head,"dir") == "TRT" then + if head.id == whatsit_code and head.subtype == localpar_code then + if head.dir == "TRT" then return 1, "TRT", true else return 0, "TLT", true @@ -799,30 +785,30 @@ local function apply_to_list(list,size,head,pardir) report_directions("fatal error, size mismatch") break end - local id = getid(current) + local id = current.id local entry = list[index] local begindir = entry.begindir local enddir = entry.enddir if id == glyph_code then local mirror = entry.mirror if mirror then - setfield(current,"char",mirror) + current.char = mirror end if trace_directions then local direction = entry.direction setcolor(current,direction,direction ~= entry.original,mirror) end elseif id == hlist_code or id == vlist_code then - setfield(current,"dir",pardir) -- is this really needed? + current.dir = pardir -- is this really needed? elseif id == glue_code then - if enddir and getsubtype(current) == parfillskip_code then + if enddir and current.subtype == parfillskip_code then -- insert the last enddir before \parfillskip glue head = insert_node_before(head,current,new_textdir(enddir)) enddir = false done = true end elseif id == whatsit_code then - if begindir and getsubtype(current) == localpar_code then + if begindir and current.subtype == localpar_code then -- local_par should always be the 1st node head, current = insert_node_after(head,current,new_textdir(begindir)) begindir = nil @@ -836,7 +822,7 @@ local function apply_to_list(list,size,head,pardir) local skip = entry.skip if skip and skip > 0 then for i=1,skip do - current = getnext(current) + current = current.next end end if enddir then @@ -844,13 +830,13 @@ local function apply_to_list(list,size,head,pardir) done = true end if not entry.remove then - current = getnext(current) + current = current.next elseif remove_controls then -- X9 head, current = remove_node(head,current,true) done = true else - current = getnext(current) + current = current.next end index = index + 1 end @@ -858,9 +844,8 @@ local function apply_to_list(list,size,head,pardir) end local function process(head) - head = tonut(head) -- for the moment a whole paragraph property - local attr = getattr(head,a_directions) + local attr = head[a_directions] local analyze_fences = getfences(attr) -- local list, size = build_list(head) @@ -879,7 +864,7 @@ local function process(head) report_directions("result : %s",show_done(list,size)) end head, done = apply_to_list(list,size,head,pardir) - return tonode(head), done + return head, done end directions.installhandler(interfaces.variables.two,process) diff --git a/tex/context/base/typo-fln.lua b/tex/context/base/typo-fln.lua index 7ce41cd81..4c97af450 100644 --- a/tex/context/base/typo-fln.lua +++ b/tex/context/base/typo-fln.lua @@ -23,38 +23,25 @@ local firstlines = typesetters.firstlines local nodes = nodes local tasks = nodes.tasks -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getid = nuts.getid -local getfield = nuts.getfield -local getlist = nuts.getlist -local getattr = nuts.getattr -local getbox = nuts.getbox - -local setfield = nuts.setfield -local setattr = nuts.setattr - +local getbox = nodes.getbox local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local disc_code = nodecodes.disc local kern_code = nodecodes.kern -local traverse_id = nuts.traverse_id -local free_node_list = nuts.flush_list -local free_node = nuts.flush_node -local copy_node_list = nuts.copy_list -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before -local hpack_node_list = nuts.hpack -local remove_node = nuts.remove +local traverse_id = nodes.traverse_id +local free_node_list = nodes.flush_list +local free_node = nodes.flush_node +local copy_node_list = nodes.copy_list +local insert_node_after = nodes.insert_after +local insert_node_before = nodes.insert_before +local hpack_node_list = nodes.hpack +local remove_node = nodes.remove -local nodepool = nuts.pool +local nodepool = nodes.pool local newpenalty = nodepool.penalty local newkern = nodepool.kern -local tracerrule = nodes.tracers.pool.nuts.rule +local tracerrule = nodes.tracers.pool.nodes.rule local actions = { } firstlines.actions = actions @@ -105,9 +92,9 @@ actions[v_line] = function(head,setting) local linebreaks = { } for g in traverse_id(glyph_code,temp) do if dynamic > 0 then - setattr(g,0,dynamic) + g[0] = dynamic end - setfield(g,"font",font) + g.font = font end local start = temp local list = temp @@ -121,7 +108,7 @@ actions[v_line] = function(head,setting) hsize = hsize - hangindent end while start do - local id = getid(start) + local id = start.id if id == glyph_code then n = n + 1 elseif id == disc_code then @@ -130,7 +117,7 @@ actions[v_line] = function(head,setting) -- this could be an option elseif n > 0 then local pack = hpack_node_list(copy_node_list(list,start)) - if getfield(pack,"width") > hsize then + if pack.width > hsize then free_node_list(pack) list = prev break @@ -141,7 +128,7 @@ actions[v_line] = function(head,setting) nofchars = n end end - start = getnext(start) + start = start.next end if not linebreaks[i] then linebreaks[i] = n @@ -152,18 +139,18 @@ actions[v_line] = function(head,setting) for i=1,noflines do local linebreak = linebreaks[i] while start and n < nofchars do - local id = getid(start) + local id = start.id if id == glyph_code then -- or id == disc_code then if dynamic > 0 then - setattr(start,0,dynamic) + start[0] = dynamic end - setfield(start,"font",font) + start.font = font if ca and ca > 0 then - setattr(start,a_colorspace,ma == 0 and 1 or ma) - setattr(start,a_color,ca) + start[a_colorspace] = ma == 0 and 1 or ma + start[a_color] = ca end if ta and ta > 0 then - setattr(start,a_transparency,ta) + start[a_transparency] = ta end n = n + 1 end @@ -176,7 +163,7 @@ actions[v_line] = function(head,setting) head, start = insert_node_after(head,start,newpenalty(-10000)) -- break break end - start = getnext(start) + start = start.next end end free_node_list(temp) @@ -195,7 +182,7 @@ actions[v_word] = function(head,setting) local ca = setting.ca local ta = setting.ta while start do - local id = getid(start) + local id = start.id -- todo: delete disc nodes if id == glyph_code then if not ok then @@ -203,16 +190,16 @@ actions[v_word] = function(head,setting) ok = true end if ca and ca > 0 then - setattr(start,a_colorspace,ma == 0 and 1 or ma) - setattr(start,a_color,ca) + start[a_colorspace] = ma == 0 and 1 or ma + start[a_color] = ca end if ta and ta > 0 then - setattr(start,a_transparency,ta) + start[a_transparency] = ta end if dynamic > 0 then - setattr(start,0,dynamic) + start[0] = dynamic end - setfield(start,"font",font) + start.font = font elseif id == disc_code then -- continue elseif id == kern_code then -- todo: fontkern @@ -223,7 +210,7 @@ actions[v_word] = function(head,setting) break end end - start = getnext(start) + start = start.next end return head, true end @@ -231,17 +218,16 @@ end actions[v_default] = actions[v_line] function firstlines.handler(head) - head = tonut(head) local start = head local attr = nil while start do - attr = getattr(start,a_firstline) + attr = start[a_firstline] if attr then break - elseif getid(start) == glyph_code then + elseif start.id == glyph then break else - start = getnext(start) + start = start.next end end if attr then @@ -254,18 +240,17 @@ function firstlines.handler(head) if trace_firstlines then report_firstlines("processing firstlines, alternative %a",alternative) end - local head, done = action(head,settings) - return tonode(head), done + return action(head,settings) end end - return tonode(head), false + return head, false end -- goodie function commands.applytofirstcharacter(box,what) local tbox = getbox(box) -- assumes hlist - local list = getlist(tbox) + local list = tbox.list local done = nil for n in traverse_id(glyph_code,list) do list = remove_node(list,n) @@ -273,10 +258,10 @@ function commands.applytofirstcharacter(box,what) break end if done then - setfield(tbox,"list",list) + tbox.list = list local kind = type(what) if kind == "string" then - context[what](tonode(done)) + context[what](done) elseif kind == "function" then what(done) else diff --git a/tex/context/base/typo-itc.lua b/tex/context/base/typo-itc.lua index db94c5c54..452b623c8 100644 --- a/tex/context/base/typo-itc.lua +++ b/tex/context/base/typo-itc.lua @@ -9,9 +9,8 @@ if not modules then modules = { } end modules ['typo-itc'] = { local utfchar = utf.char local trace_italics = false trackers.register("typesetters.italics", function(v) trace_italics = v end) -local report_italics = logs.reporter("nodes","italics") -local threshold = 0.5 trackers.register("typesetters.threshold", function(v) threshold = v == true and 0.5 or tonumber(v) end) +local report_italics = logs.reporter("nodes","italics") typesetters.italics = typesetters.italics or { } local italics = typesetters.italics @@ -25,35 +24,21 @@ local math_code = nodecodes.math local tasks = nodes.tasks -local nuts = nodes.nuts -local nodepool = nuts.pool - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local getfield = nuts.getfield -local getnext = nuts.getnext -local getid = nuts.getid -local getfont = nuts.getfont -local getchar = nuts.getchar -local getattr = nuts.getattr - -local insert_node_after = nuts.insert_after -local delete_node = nuts.delete -local end_of_math = nuts.end_of_math +local insert_node_after = node.insert_after +local delete_node = nodes.delete +local end_of_math = node.end_of_math local texgetattribute = tex.getattribute local texsetattribute = tex.setattribute local a_italics = attributes.private("italics") local unsetvalue = attributes.unsetvalue -local new_correction_kern = nodepool.fontkern -local new_correction_glue = nodepool.glue +local new_correction_kern = nodes.pool.fontkern +local new_correction_glue = nodes.pool.glue local fonthashes = fonts.hashes local fontdata = fonthashes.identifiers local italicsdata = fonthashes.italics -local exheights = fonthashes.exheights local forcedvariant = false @@ -98,7 +83,6 @@ end -- todo: clear attribute function italics.handler(head) - head = tonut(head) local done = false local italic = 0 local lastfont = nil @@ -108,10 +92,10 @@ function italics.handler(head) local current = head local inserted = nil while current do - local id = getid(current) + local id = current.id if id == glyph_code then - local font = getfont(current) - local char = getchar(current) + local font = current.font + local char = current.char local data = italicsdata[font] if font ~= lastfont then if italic ~= 0 then @@ -120,25 +104,11 @@ function italics.handler(head) report_italics("ignoring %p between italic %C and italic %C",italic,prevchar,char) end else - local okay = true - if threshold then - local ht = getfield(current,"height") - local ex = exheights[font] - local th = threshold * ex - if ht <= th then - if trace_italics then - report_italics("ignoring correction between italic %C and regular %C, height %p less than threshold %p",prevchar,char,ht,th) - end - okay = false - end - end - if okay then - if trace_italics then - report_italics("inserting %p between italic %C and regular %C",italic,prevchar,char) - end - insert_node_after(head,previous,new_correction_kern(italic)) - done = true + if trace_italics then + report_italics("inserting %p between italic %C and regular %C",italic,prevchar,char) end + insert_node_after(head,previous,new_correction_kern(italic)) + done = true end elseif inserted and data then if trace_italics then @@ -151,7 +121,7 @@ function italics.handler(head) lastfont = font end if data then - local attr = forcedvariant or getattr(current,a_italics) + local attr = forcedvariant or current[a_italics] if attr and attr > 0 then local cd = data[char] if not cd then @@ -203,7 +173,7 @@ function italics.handler(head) italic = 0 done = true end - current = getnext(current) + current = current.next end if italic ~= 0 and lastattr > 1 then -- more control is needed here if trace_italics then @@ -212,7 +182,7 @@ function italics.handler(head) insert_node_after(head,previous,new_correction_kern(italic)) done = true end - return tonode(head), done + return head, done end local enable @@ -254,7 +224,6 @@ function commands.setupitaliccorrection(option) -- no grouping ! elseif options[variables.always] then variant = 2 end - -- maybe also keywords for threshold if options[variables.global] then forcedvariant = variant texsetattribute(a_italics,unsetvalue) diff --git a/tex/context/base/typo-krn.lua b/tex/context/base/typo-krn.lua index a8ffe557b..56f58bb73 100644 --- a/tex/context/base/typo-krn.lua +++ b/tex/context/base/typo-krn.lua @@ -13,36 +13,21 @@ local utfchar = utf.char local nodes, node, fonts = nodes, node, fonts -local tasks = nodes.tasks -local nuts = nodes.nuts -local nodepool = nuts.pool - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local find_node_tail = nuts.tail -local free_node = nuts.free -local free_nodelist = nuts.flush_list -local copy_node = nuts.copy -local copy_nodelist = nuts.copy_list -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local end_of_math = nuts.end_of_math - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -local getfont = nuts.getfont -local getsubtype = nuts.getsubtype -local getchar = nuts.getchar +local find_node_tail = node.tail or node.slide +local free_node = node.free +local free_nodelist = node.flush_list +local copy_node = node.copy +local copy_nodelist = node.copy_list +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local end_of_math = node.end_of_math local texsetattribute = tex.setattribute local unsetvalue = attributes.unsetvalue +local nodepool = nodes.pool +local tasks = nodes.tasks + local new_gluespec = nodepool.gluespec local new_kern = nodepool.kern local new_glue = nodepool.glue @@ -122,10 +107,10 @@ kerns.keeptogether = false -- just for fun (todo: control setting with key/value -- blue : keep by goodie function kerns.keepligature(n) -- might become default - local f = getfont(n) - local a = getattr(n,0) or 0 + local f = n.font + local a = n[0] or 0 if trace_ligatures then - local c = getchar(n) + local c = n.char local d = fontdescriptions[f][c].name if a > 0 and contextsetups[a].keepligatures == v_auto then report("font %!font:name!, glyph %a, slot %X -> ligature %s, by %s feature %a",f,d,c,"kept","dynamic","keepligatures") @@ -184,9 +169,9 @@ end local function kern_injector(fillup,kern) if fillup then local g = new_glue(kern) - local s = getfield(g,"spec") - setfield(s,"stretch",kern) - setfield(s,"stretch_order",1) + local s = g.spec + s.stretch = kern + s.stretch_order = 1 return g else return new_kern(kern) @@ -196,7 +181,7 @@ end local function spec_injector(fillup,width,stretch,shrink) if fillup then local s = new_gluespec(width,2*stretch,2*shrink) - setfield(s,"stretch_order",1) + s.stretch_order = 1 return s else return new_gluespec(width,stretch,shrink) @@ -212,9 +197,9 @@ local function do_process(head,force) -- todo: glue so that we can fully stretch local fillup = false while start do -- faster to test for attr first - local attr = force or getattr(start,a_kerns) + local attr = force or start[a_kerns] if attr and attr > 0 then - setattr(start,a_kerns,unsetvalue) + start[a_kerns] = unsetvalue local krn = mapping[attr] if krn == v_max then krn = .25 @@ -223,10 +208,10 @@ local function do_process(head,force) -- todo: glue so that we can fully stretch fillup = false end if krn and krn ~= 0 then - local id = getid(start) - if id == glyph_code then -- we could use the subtype ligature - lastfont = getfont(start) - local c = getfield(start,"components") + local id = start.id + if id == glyph_code then + lastfont = start.font + local c = start.components if not c then -- fine elseif keepligature and keepligature(start) then @@ -234,47 +219,47 @@ local function do_process(head,force) -- todo: glue so that we can fully stretch else c = do_process(c,attr) local s = start - local p, n = getprev(s), getnext(s) + local p, n = s.prev, s.next local tail = find_node_tail(c) if p then - setfield(p,"next",c) - setfield(c,"prev",p) + p.next = c + c.prev = p else head = c end if n then - setfield(n,"prev",tail) + n.prev = tail end - setfield(tail,"next",n) + tail.next = n start = c - setfield(s,"components",nil) + s.components = nil -- we now leak nodes ! - -- free_node(s) + -- free_node(s) done = true end - local prev = getprev(start) + local prev = start.prev if not prev then -- skip - elseif markdata[lastfont][getchar(start)] then + elseif markdata[lastfont][start.char] then -- skip else - local pid = getid(prev) + local pid = prev.id if not pid then -- nothing elseif pid == kern_code then - if getsubtype(prev) == kerning_code or getattr(prev,a_fontkern) then - if keeptogether and getid(getprev(prev)) == glyph_code and keeptogether(getprev(prev),start) then -- we could also pass start + if prev.subtype == kerning_code or prev[a_fontkern] then + if keeptogether and prev.prev.id == glyph_code and keeptogether(prev.prev,start) then -- we could also pass start -- keep 'm else -- not yet ok, as injected kerns can be overlays (from node-inj.lua) - setfield(prev,"subtype",userkern_code) - setfield(prev,"kern",getfield(prev,"kern") + quaddata[lastfont]*krn) -- here + prev.subtype = userkern_code + prev.kern = prev.kern + quaddata[lastfont]*krn -- here done = true end end elseif pid == glyph_code then - if getfont(prev) == lastfont then - local prevchar, lastchar = getchar(prev), getchar(start) + if prev.font == lastfont then + local prevchar, lastchar = prev.char, start.char if keeptogether and keeptogether(prev,start) then -- keep 'm else @@ -293,102 +278,102 @@ local function do_process(head,force) -- todo: glue so that we can fully stretch -- a bit too complicated, we can best not copy and just calculate -- but we could have multiple glyphs involved so ... local disc = prev -- disc - local prv, nxt = getprev(disc), getnext(disc) - if getsubtype(disc) == discretionary_code then + local prv, nxt = disc.prev, disc.next + if disc.subtype == discretionary_code then -- maybe we should forget about this variant as there is no glue -- possible - local pre, post, replace = getfield(disc,"pre"), getfield(disc,"post"), getfield(disc,"replace") - if pre and prv then -- must pair with getprev(start) + local pre, post, replace = disc.pre, disc.post, disc.replace + if pre and prv then -- must pair with start.prev + -- this one happens in most cases local before = copy_node(prv) - setfield(pre,"prev",before) - setfield(before,"next",pre) - setfield(before,"prev",nil) + pre.prev = before + before.next = pre + before.prev = nil pre = do_process(before,attr) - pre = getnext(pre) - setfield(pre,"prev",nil) - setfield(disc,"pre",pre) + pre = pre.next + pre.prev = nil + disc.pre = pre free_node(before) end if post and nxt then -- must pair with start local after = copy_node(nxt) local tail = find_node_tail(post) - setfield(tail,"next",after) - setfield(after,"prev",tail) - setfield(after,"next",nil) + tail.next = after + after.prev = tail + after.next = nil post = do_process(post,attr) - setfield(tail,"next",nil) - setfield(disc,"post",post) + tail.next = nil + disc.post = post free_node(after) end if replace and prv and nxt then -- must pair with start and start.prev local before = copy_node(prv) local after = copy_node(nxt) local tail = find_node_tail(replace) - setfield(replace,"prev",before) - setfield(before,"next",replace) - setfield(before,"prev",nil) - setfield(tail,"next",after) - setfield(after,"prev",tail) - setfield(after,"next",nil) + replace.prev = before + before.next = replace + before.prev = nil + tail.next = after + after.prev = tail + after.next = nil replace = do_process(before,attr) - replace = getnext(replace) - setfield(replace,"prev",nil) - setfield(getfield(after,"prev"),"next",nil) - setfield(disc,"replace",replace) + replace = replace.next + replace.prev = nil + after.prev.next = nil + disc.replace = replace free_node(after) free_node(before) - elseif prv and getid(prv) == glyph_code and getfont(prv) == lastfont then - local prevchar, lastchar = getchar(prv), getchar(start) + elseif prv and prv.id == glyph_code and prv.font == lastfont then + local prevchar, lastchar = prv.char, start.char local kerns = chardata[lastfont][prevchar].kerns local kern = kerns and kerns[lastchar] or 0 krn = kern + quaddata[lastfont]*krn -- here - setfield(disc,"replace",kern_injector(false,krn)) -- only kerns permitted, no glue + disc.replace = kern_injector(false,krn) -- only kerns permitted, no glue else krn = quaddata[lastfont]*krn -- here - setfield(disc,"replace",kern_injector(false,krn)) -- only kerns permitted, no glue + disc.replace = kern_injector(false,krn) -- only kerns permitted, no glue end else -- this one happens in most cases: automatic (-), explicit (\-), regular (patterns) - if prv and getid(prv) == glyph_code and getfont(prv) == lastfont then - -- the normal case - local prevchar, lastchar = getchar(prv), getchar(start) + if prv and prv.id == glyph_code and prv.font == lastfont then + local prevchar, lastchar = prv.char, start.char local kerns = chardata[lastfont][prevchar].kerns local kern = kerns and kerns[lastchar] or 0 - krn = kern + quaddata[lastfont]*krn + krn = kern + quaddata[lastfont]*krn -- here else - krn = quaddata[lastfont]*krn + krn = quaddata[lastfont]*krn -- here end insert_node_before(head,start,kern_injector(fillup,krn)) end end end elseif id == glue_code then - local subtype = getsubtype(start) + local subtype = start.subtype if subtype == userskip_code or subtype == xspaceskip_code or subtype == spaceskip_code then - local s = getfield(start,"spec") - local w = getfield(s,"width") + local s = start.spec + local w = s.width if w > 0 then - local width, stretch, shrink = w+gluefactor*w*krn, getfield(s,"stretch"), getfield(s,"shrink") - setfield(start,"spec",spec_injector(fillup,width,stretch*width/w,shrink*width/w)) + local width, stretch, shrink = w+gluefactor*w*krn, s.stretch, s.shrink + start.spec = spec_injector(fillup,width,stretch*width/w,shrink*width/w) done = true end end elseif id == kern_code then - -- if getsubtype(start) == kerning_code then -- handle with glyphs - -- local sk = getfield(start,"kern") + -- if start.subtype == kerning_code then -- handle with glyphs + -- local sk = start.kern -- if sk > 0 then - -- setfield(start,"kern",sk*krn) + -- start.kern = sk*krn -- done = true -- end -- end elseif lastfont and (id == hlist_code or id == vlist_code) then -- todo: lookahead - local p = getprev(start) - if p and getid(p) ~= glue_code then + local p = start.prev + if p and p.id ~= glue_code then insert_node_before(head,start,kern_injector(fillup,quaddata[lastfont]*krn)) done = true end - local n = getnext(start) - if n and getid(n) ~= glue_code then + local n = start.next + if n and n.id ~= glue_code then insert_node_after(head,start,kern_injector(fillup,quaddata[lastfont]*krn)) done = true end @@ -398,7 +383,7 @@ local function do_process(head,force) -- todo: glue so that we can fully stretch end end if start then - start = getnext(start) + start = start.next end end return head, done @@ -429,8 +414,7 @@ function kerns.set(factor) end function kerns.handler(head) - local head, done = do_process(tonut(head)) -- no direct map, because else fourth argument is tail == true - return tonode(head), done + return do_process(head) -- no direct map, because else fourth argument is tail == true end -- interface diff --git a/tex/context/base/typo-mar.lua b/tex/context/base/typo-mar.lua index 4bfc107ad..85d5c85a8 100644 --- a/tex/context/base/typo-mar.lua +++ b/tex/context/base/typo-mar.lua @@ -115,30 +115,13 @@ local v_first = variables.first local v_text = variables.text local v_column = variables.column -local nuts = nodes.nuts -local nodepool = nuts.pool - -local tonode = nuts.tonode -local tonut = nuts.tonut - -local copy_node_list = nuts.copy_list -local hpack_nodes = nuts.hpack -- nodes.fasthpack not really faster here -local traverse_id = nuts.traverse_id -local free_node_list = nuts.flush_list -local insert_node_after = nuts.insert_after -local insert_node_before = nuts.insert_before -local linked_nodes = nuts.linked - -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr -local getsubtype = nuts.getsubtype -local getbox = nuts.getbox -local getlist = nuts.getlist +local copy_node_list = node.copy_list +local slide_nodes = node.slide +local hpack_nodes = node.hpack -- nodes.fasthpack not really faster here +local traverse_id = node.traverse_id +local free_node_list = node.flush_list +local insert_node_after = node.insert_after +local insert_node_before = node.insert_before local nodecodes = nodes.nodecodes local listcodes = nodes.listcodes @@ -161,7 +144,7 @@ local userdefined_code = whatsitcodes.userdefined local dir_code = whatsitcodes.dir local localpar_code = whatsitcodes.localpar -local nodepool = nuts.pool +local nodepool = nodes.pool local new_kern = nodepool.kern local new_glue = nodepool.glue @@ -172,12 +155,13 @@ local new_latelua = nodepool.latelua local texgetcount = tex.getcount local texgetdimen = tex.getdimen +local texgetbox = tex.getbox local texget = tex.get local points = number.points local isleftpage = layouts.status.isleftpage -local registertogether = builders.paragraphs.registertogether -- tonode +local registertogether = builders.paragraphs.registertogether local jobpositions = job.positions local getposition = jobpositions.position @@ -186,7 +170,7 @@ local a_margindata = attributes.private("margindata") local inline_mark = nodepool.userids["margins.inline"] -local margins = { } +local margins = { } typesetters.margins = margins local locations = { v_left, v_right, v_inner, v_outer } -- order might change @@ -249,7 +233,7 @@ local function showstore(store,banner,location) if next(store) then for i, si in table.sortedpairs(store) do local si =store[i] - report_margindata("%s: stored in %a at %s: %a => %s",banner,location,i,validstring(si.name,"no name"),nodes.toutf(getlist(si.box))) + report_margindata("%s: stored in %a at %s: %a => %s",banner,location,i,validstring(si.name,"no name"),nodes.toutf(si.box.list)) end else report_margindata("%s: nothing stored in location %a",banner,location) @@ -258,7 +242,7 @@ end function margins.save(t) setmetatable(t,defaults) - local content = getbox(t.number) + local content = texgetbox(t.number) local location = t.location local category = t.category local inline = t.inline @@ -326,11 +310,11 @@ function margins.save(t) -- nice is to make a special status table mechanism local leftmargindistance = texgetdimen("naturalleftmargindistance") local rightmargindistance = texgetdimen("naturalrightmargindistance") - local strutbox = getbox("strutbox") - t.strutdepth = getfield(strutbox,"depth") - t.strutheight = getfield(strutbox,"height") - t.leftskip = getfield(texget("leftskip"),"width") -- we're not in forgetall - t.rightskip = getfield(texget("rightskip"),"width") -- we're not in forgetall + local strutbox = texgetbox("strutbox") + t.strutdepth = strutbox.depth + t.strutheight = strutbox.height + t.leftskip = texget("leftskip").width -- we're not in forgetall + t.rightskip = texget("rightskip").width -- we're not in forgetall t.leftmargindistance = leftmargindistance -- todo:layoutstatus table t.rightmargindistance = rightmargindistance t.leftedgedistance = texgetdimen("naturalleftedgedistance") @@ -343,7 +327,7 @@ function margins.save(t) -- -- t.realpageno = texgetcount("realpageno") if inline then - context(tonode(new_usernumber(inline_mark,nofsaved))) -- or use a normal node + context(new_usernumber(inline_mark,nofsaved)) store[nofsaved] = t -- no insert nofinlined = nofinlined + 1 else @@ -420,7 +404,7 @@ local function realign(current,candidate) -- we assume that list is a hbox, otherwise we had to take the whole current -- in order to get it right - setfield(current,"width",0) + current.width = 0 local anchornode, move_x -- this mess is needed for alignments (combinations) so we use that @@ -462,9 +446,9 @@ local function realign(current,candidate) report_margindata("realigned %a, location %a, margin %a",candidate.n,location,margin) end end - local list = hpack_nodes(linked_nodes(anchornode,new_kern(-delta),getlist(current),new_kern(delta))) - setfield(current,"list",list) - setfield(current,"width",0) + + current.list = hpack_nodes(anchornode .. new_kern(-delta) .. current.list .. new_kern(delta)) + current.width = 0 end local function realigned(current,a) @@ -506,8 +490,7 @@ local function markovershoot(current) v_anchors = v_anchors + 1 cache[v_anchors] = stacked local anchor = new_latelua(format("typesetters.margins.ha(%s)",v_anchors)) -- todo: alleen als offset > line - local list = hpack_nodes(linked_nodes(anchor,getlist(current))) - setfield(current,"list",list) + current.list = hpack_nodes(anchor .. current.list) end local function getovershoot(location) @@ -529,10 +512,10 @@ end local function inject(parent,head,candidate) local box = candidate.box - local width = getfield(box,"width") - local height = getfield(box,"height") - local depth = getfield(box,"depth") - local shift = getfield(box,"shift") + local width = box.width + local height = box.height + local depth = box.depth + local shift = box.shift local stack = candidate.stack local location = candidate.location local method = candidate.method @@ -541,7 +524,7 @@ local function inject(parent,head,candidate) local baseline = candidate.baseline local strutheight = candidate.strutheight local strutdepth = candidate.strutdepth - local psubtype = getsubtype(parent) + local psubtype = parent.subtype local offset = stacked[location] local firstonstack = offset == false or offset == nil nofstatus = nofstatus + 1 @@ -563,7 +546,7 @@ local function inject(parent,head,candidate) end end candidate.width = width - candidate.hsize = getfield(parent,"width") -- we can also pass textwidth + candidate.hsize = parent.width -- we can also pass textwidth candidate.psubtype = psubtype if trace_margindata then report_margindata("processing, index %s, height %p, depth %p, parent %s",candidate.n,height,depth,listcodes[psubtype]) @@ -590,7 +573,7 @@ local function inject(parent,head,candidate) -- experimental. -- -- -- if method == v_top then - local delta = height - getfield(parent,"height") + local delta = height - parent.height if trace_margindata then report_margindata("top aligned by %p",delta) end @@ -633,23 +616,22 @@ local function inject(parent,head,candidate) shift = shift + delta offset = offset + delta end - setfield(box,"shift",shift) - setfield(box,"width",0) + box.shift = shift + box.width = 0 if not head then head = box - elseif getid(head) == whatsit_code and getsubtype(head) == localpar_code then + elseif head.id == whatsit_code and head.subtype == localpar_code then -- experimental - if getfield(head,"dir") == "TRT" then - local list = hpack_nodes(linked_nodes(new_kern(candidate.hsize),getlist(box),new_kern(-candidate.hsize))) - setfield(box,"list",list) + if head.dir == "TRT" then + box.list = hpack_nodes(new_kern(candidate.hsize) .. box.list .. new_kern(-candidate.hsize)) end insert_node_after(head,head,box) else - setfield(head,"prev",box) - setfield(box,"next",head) + head.prev = box + box.next = head head = box end - setattr(box,a_margindata,nofstatus) + box[a_margindata] = nofstatus if trace_margindata then report_margindata("injected, location %a, shift %p",location,shift) end @@ -674,12 +656,12 @@ local function flushinline(parent,head) local current = head local done = false local continue = false - local room, don, con, list + local room, don, con while current and nofinlined > 0 do - local id = getid(current) + local id = current.id if id == whatsit_code then - if getsubtype(current) == userdefined_code and getfield(current,"user_id") == inline_mark then - local n = getfield(current,"value") + if current.subtype == userdefined_code and current.user_id == inline_mark then + local n = current.value local candidate = inlinestore[n] if candidate then -- no vpack, as we want to realign inlinestore[n] = nil @@ -692,12 +674,11 @@ local function flushinline(parent,head) end elseif id == hlist_code or id == vlist_code then -- optional (but sometimes needed) - list, don, con = flushinline(current,getlist(current)) - setfield(current,"list",list) + current.list, don, con = flushinline(current,current.list) continue = continue or con done = done or don end - current = getnext(current) + current = current.next end return head, done, continue end @@ -705,7 +686,7 @@ end local a_linenumber = attributes.private('linenumber') local function flushed(scope,parent) -- current is hlist - local head = getlist(parent) + local head = parent.list local done = false local continue = false local room, con, don @@ -721,7 +702,7 @@ local function flushed(scope,parent) -- current is hlist done = true continue = continue or con nofstored = nofstored - 1 - registertogether(tonode(parent),room) -- !! tonode + registertogether(parent,room) else break end @@ -730,18 +711,17 @@ local function flushed(scope,parent) -- current is hlist end if nofinlined > 0 then if done then - setfield(parent,"list",head) + parent.list = head end head, don, con = flushinline(parent,head) continue = continue or con done = done or don end if done then - local a = getattr(head,a_linenumber) -- hack .. we need a more decent critical attribute inheritance mechanism - local l = hpack_nodes(head,getfield(parent,"width"),"exactly") - setfield(parent,"list",l) + local a = head[a_linenumber] -- hack .. we need a more decent critical attribute inheritance mechanism + parent.list = hpack_nodes(head,parent.width,"exactly") if a then - setattr(l,a_linenumber,a) + parent.list[a_linenumber] = a end -- resetstacked() end @@ -756,15 +736,14 @@ local function handler(scope,head,group) if trace_margindata then report_margindata("flushing stage one, stored %s, scope %s, delayed %s, group %a",nofstored,scope,nofdelayed,group) end - head = tonut(head) local current = head local done = false while current do - local id = getid(current) - if (id == vlist_code or id == hlist_code) and not getattr(current,a_margindata) then + local id = current.id + if (id == vlist_code or id == hlist_code) and not current[a_margindata] then local don, continue = flushed(scope,current) if don then - setattr(current,a_margindata,0) -- signal to prevent duplicate processing + current[a_margindata] = 0 -- signal to prevent duplicate processing if continue then markovershoot(current) end @@ -774,12 +753,12 @@ local function handler(scope,head,group) done = true end end - current = getnext(current) + current = current.next end -- if done then resetstacked() -- why doesn't done work ok here? -- end - return tonode(head), done + return head, done else return head, false end @@ -832,11 +811,11 @@ local function finalhandler(head) local current = head local done = false while current do - local id = getid(current) + local id = current.id if id == hlist_code then - local a = getattr(current,a_margindata) + local a = current[a_margindata] if not a or a == 0 then - finalhandler(getlist(current)) + finalhandler(current.list) elseif realigned(current,a) then done = true if nofdelayed == 0 then @@ -844,9 +823,9 @@ local function finalhandler(head) end end elseif id == vlist_code then - finalhandler(getlist(current)) + finalhandler(current.list) end - current = getnext(current) + current = current.next end return head, done else @@ -859,10 +838,7 @@ function margins.finalhandler(head) -- if trace_margindata then -- report_margindata("flushing stage two, instore: %s, delayed: %s",nofstored,nofdelayed) -- end -head = tonut(head) -local head, done = finalhandler(head) -head = tonode(head) - return head, done + return finalhandler(head) else return head, false end diff --git a/tex/context/base/typo-pag.lua b/tex/context/base/typo-pag.lua index 5b96e9c21..0dd75ddf9 100644 --- a/tex/context/base/typo-pag.lua +++ b/tex/context/base/typo-pag.lua @@ -6,14 +6,6 @@ if not modules then modules = { } end modules ['typo-pag'] = { license = "see context related readme files" } - -builders = builders or { } -local builders = builders - -builders.paragraphs = builders.paragraphs or { } -local parbuilders = builders.paragraphs - -local nodes = nodes local nodecodes = nodes.nodecodes local hlist_code = nodecodes.hlist @@ -22,22 +14,12 @@ local glue_code = nodecodes.glue local kern_code = nodecodes.kern local penalty_code = nodecodes.penalty -local unsetvalue = attributes.unsetvalue -local a_keeptogether = attributes.private("keeptogether") - -local nuts = nodes.nuts -local tonut = nuts.tonut +local insert_node_after = node.insert_after +local new_penalty = nodes.pool.penalty -local getfield = nuts.getfield -local setfield = nuts.setfield -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getattr = nuts.getattr -local setattr = nuts.setattr +local unsetvalue = attributes.unsetvalue -local insert_node_after = nuts.insert_after -local new_penalty = nuts.pool.penalty +local a_keeptogether = attributes.private("keeptogether") local trace_keeptogether = false local report_keeptogether = logs.reporter("parbuilders","keeptogether") @@ -51,11 +33,11 @@ trackers.register("parbuilders.keeptogether", function(v) trace_keeptogether = -- todo: also support lines = 3 etc (e.g. dropped caps) but how to set that -- when no hlists are there ? ... maybe the local_par -function parbuilders.registertogether(line,specification) -- might change +function builders.paragraphs.registertogether(line,specification) -- might change if not enabled then nodes.tasks.enableaction("finalizers","builders.paragraphs.keeptogether") end - local a = getattr(line,a_keeptogether) + local a = line[a_keeptogether] local c = a and cache[a] if c then local height = specification.height @@ -82,7 +64,7 @@ function parbuilders.registertogether(line,specification) -- might change if not specification.slack then specification.slack = 0 end - setattr(line,a_keeptogether,last) + line[a_keeptogether] = last end if trace_keeptogether then local a = a or last @@ -106,24 +88,24 @@ local function keeptogether(start,a) if start then local specification = cache[a] if a then - local current = getnext(start) + local current = start.next local previous = start - local total = getfield(previous,"depth") + local total = previous.depth local slack = specification.slack local threshold = specification.depth - slack if trace_keeptogether then report_keeptogether("%s, index %s, total %p, threshold %p, slack %p","list",a,total,threshold,slack) end while current do - local id = getid(current) + local id = current.id if id == vlist_code or id == hlist_code then - total = total + getfield(current,"height") + getfield(current,"depth") + total = total + current.height + current.depth if trace_keeptogether then report_keeptogether("%s, index %s, total %p, threshold %p","list",a,total,threshold) end if total <= threshold then - if getid(previous) == penalty_code then - setfield(previous,"penalty",10000) + if previous.id == penalty_code then + previous.penalty = 10000 else insert_node_after(head,previous,new_penalty(10000)) end @@ -132,13 +114,13 @@ local function keeptogether(start,a) end elseif id == glue_code then -- hm, breakpoint, maybe turn this into kern - total = total + getfield(getfield(current,"spec"),"width") + total = total + current.spec.width if trace_keeptogether then report_keeptogether("%s, index %s, total %p, threshold %p","glue",a,total,threshold) end if total <= threshold then - if getid(previous) == penalty_code then - setfield(previous,"penalty",10000) + if previous.id == penalty_code then + previous.penalty = 10000 else insert_node_after(head,previous,new_penalty(10000)) end @@ -146,13 +128,13 @@ local function keeptogether(start,a) break end elseif id == kern_code then - total = total + getfield(current,"kern") + total = total + current.kern if trace_keeptogether then report_keeptogether("%s, index %s, total %s, threshold %s","kern",a,total,threshold) end if total <= threshold then - if getid(previous) == penalty_code then - setfield(previous,"penalty",10000) + if previous.id == penalty_code then + previous.penalty = 10000 else insert_node_after(head,previous,new_penalty(10000)) end @@ -161,16 +143,16 @@ local function keeptogether(start,a) end elseif id == penalty_code then if total <= threshold then - if getid(previous) == penalty_code then - setfield(previous,"penalty",10000) + if previous.id == penalty_code then + previous.penalty = 10000 end - setfield(current,"penalty",10000) + current.penalty = 10000 else break end end previous = current - current = getnext(current) + current = current.next end end end @@ -178,20 +160,20 @@ end -- also look at first non glue/kern node e.g for a dropped caps -function parbuilders.keeptogether(head) +function builders.paragraphs.keeptogether(head) local done = false - local current = tonut(head) + local current = head while current do - if getid(current) == hlist_code then - local a = getattr(current,a_keeptogether) + if current.id == hlist_code then + local a = current[a_keeptogether] if a and a > 0 then keeptogether(current,a) - setattr(current,a_keeptogether,unsetvalue) + current[a_keeptogether] = unsetvalue cache[a] = nil done = true end end - current = getnext(current) + current = current.next end return head, done end diff --git a/tex/context/base/typo-par.mkiv b/tex/context/base/typo-par.mkiv deleted file mode 100644 index 8572f31b8..000000000 --- a/tex/context/base/typo-par.mkiv +++ /dev/null @@ -1,29 +0,0 @@ -%D \module -%D [ file=typo-par, -%D version=2008.09.30, -%D title=\CONTEXT\ Typesetting Macros, -%D subtitle=Paragraph Building, -%D author=Hans Hagen, -%D date=\currentdate, -%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] -%C -%C This module is part of the \CONTEXT\ macro||package and is -%C therefore copyrighted by \PRAGMA. See mreadme.pdf for -%C details. - -\writestatus{loading}{ConTeXt Node Macros / Paragraph Building} - -%D This is very experimental, undocumented, subjected to changes, etc. just as -%D the underlying interfaces. But at least it's cleaned as part of the status-mkiv -%D cleanup. - -% \startparbuilder[basic] -% \input tufte \par -% \stopparbuilder - -\unprotect - -\registerctxluafile{node-ltp}{1.001} -\registerctxluafile{trac-par}{1.001} - -\protect \endinput diff --git a/tex/context/base/typo-rep.lua b/tex/context/base/typo-rep.lua index 95b801e2e..01868f490 100644 --- a/tex/context/base/typo-rep.lua +++ b/tex/context/base/typo-rep.lua @@ -10,44 +10,31 @@ if not modules then modules = { } end modules ['typo-rep'] = { -- endure it by listening to a couple cd's by The Scene and The Lau -- on the squeezebox on my desk. -local next, type, tonumber = next, type, tonumber - local trace_stripping = false trackers.register("nodes.stripping", function(v) trace_stripping = v end) trackers.register("fonts.stripping", function(v) trace_stripping = v end) local report_stripping = logs.reporter("fonts","stripping") -local nodes = nodes -local tasks = nodes.tasks - -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getchar = nuts.getchar -local getid = nuts.getid -local getattr = nuts.getid +local nodes, node = nodes, node -local setattr = nuts.setattr - -local delete_node = nuts.delete -local replace_node = nuts.replace -local copy_node = nuts.copy - -local nodecodes = nodes.nodecodes -local glyph_code = nodecodes.glyph +local delete_node = nodes.delete +local replace_node = nodes.replace +local copy_node = node.copy local chardata = characters.data local collected = false +local a_stripping = attributes.private("stripping") local fontdata = fonts.hashes.identifiers +local tasks = nodes.tasks -local a_stripping = attributes.private("stripping") local texsetattribute = tex.setattribute local unsetvalue = attributes.unsetvalue local v_reset = interfaces.variables.reset +local nodecodes = nodes.nodecodes +local glyph_code = nodecodes.glyph + -- todo: other namespace -> typesetters nodes.stripping = nodes.stripping or { } local stripping = nodes.stripping @@ -72,13 +59,13 @@ local function process(what,head,current,char) head, current = delete_node(head,current) elseif type(what) == "function" then head, current = what(head,current) - current = getnext(current) + current = current.next if trace_stripping then report_stripping("processing %C in text",char) end elseif what then -- assume node head, current = replace_node(head,current,copy_node(what)) - current = getnext(current) + current = current.next if trace_stripping then report_stripping("replacing %C in text",char) end @@ -87,29 +74,28 @@ local function process(what,head,current,char) end function nodes.handlers.stripping(head) - head = tonut(head) local current, done = head, false while current do - if getid(current) == glyph_code then + if current.id == glyph_code then -- it's more efficient to keep track of what needs to be kept - local todo = getattr(current,a_stripping) + local todo = current[a_stripping] if todo == 1 then - local char = getchar(current) + local char = current.char local what = glyphs[char] if what then head, current = process(what,head,current,char) done = true else -- handling of spacing etc has to be done elsewhere - current = getnext(current) + current = current.next end else - current = getnext(current) + current = current.next end else - current = getnext(current) + current = current.next end end - return tonode(head), done + return head, done end local enabled = false diff --git a/tex/context/base/typo-spa.lua b/tex/context/base/typo-spa.lua index 5cf9ab837..c3f50fe98 100644 --- a/tex/context/base/typo-spa.lua +++ b/tex/context/base/typo-spa.lua @@ -15,7 +15,10 @@ local report_spacing = logs.reporter("typesetting","spacing") local nodes, fonts, node = nodes, fonts, node -local tasks = nodes.tasks +local insert_node_before = node.insert_before +local insert_node_after = node.insert_after +local remove_node = nodes.remove +local end_of_math = node.end_of_math local fonthashes = fonts.hashes local fontdata = fonthashes.identifiers @@ -26,28 +29,6 @@ local unsetvalue = attributes.unsetvalue local v_reset = interfaces.variables.reset -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode - -local getnext = nuts.getnext -local getprev = nuts.getprev -local getchar = nuts.getchar -local getid = nuts.getid -local getfont = nuts.getfont -local getattr = nuts.getattr - -local setattr = nuts.setattr - -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local remove_node = nuts.remove -local end_of_math = nuts.end_of_math - -local nodepool = nuts.pool -local new_penalty = nodepool.penalty -local new_glue = nodepool.glue - local nodecodes = nodes.nodecodes local glyph_code = nodecodes.glyph local math_code = nodecodes.math @@ -55,6 +36,12 @@ local math_code = nodecodes.math local somespace = nodes.somespace local somepenalty = nodes.somepenalty +local nodepool = nodes.pool +local tasks = nodes.tasks + +local new_penalty = nodepool.penalty +local new_glue = nodepool.glue + typesetters = typesetters or { } local typesetters = typesetters @@ -65,6 +52,7 @@ spacings.mapping = spacings.mapping or { } spacings.numbers = spacings.numbers or { } local a_spacings = attributes.private("spacing") +spacings.attribute = a_spacings storage.register("typesetters/spacings/mapping", spacings.mapping, "typesetters.spacings.mapping") @@ -79,30 +67,29 @@ end -- todo cache lastattr function spacings.handler(head) - head = tonut(head) local done = false local start = head -- head is always begin of par (whatsit), so we have at least two prev nodes -- penalty followed by glue while start do - local id = getid(start) + local id = start.id if id == glyph_code then - local attr = getattr(start,a_spacings) + local attr = start[a_spacings] if attr and attr > 0 then local data = mapping[attr] if data then - local char = getchar(start) + local char = start.char local map = data.characters[char] - setattr(start,a_spacings,unsetvalue) -- needed? + start[a_spacings] = unsetvalue -- needed? if map then local left = map.left local right = map.right local alternative = map.alternative - local quad = quaddata[getfont(start)] - local prev = getprev(start) + local quad = quaddata[start.font] + local prev = start.prev if left and left ~= 0 and prev then local ok = false - local prevprev = getprev(prev) + local prevprev = prev.prev if alternative == 1 then local somespace = somespace(prev,true) if somespace then @@ -133,10 +120,10 @@ function spacings.handler(head) done = true end end - local next = getnext(start) + local next = start.next if right and right ~= 0 and next then local ok = false - local nextnext = getnext(next) + local nextnext = next.next if alternative == 1 then local somepenalty = somepenalty(next,10000) if somepenalty then @@ -177,10 +164,10 @@ function spacings.handler(head) start = end_of_math(start) -- weird, can return nil .. no math end? end if start then - start = getnext(start) + start = start.next end end - return tonode(head), done + return head, done end local enabled = false diff --git a/tex/context/base/typo-tal.lua b/tex/context/base/typo-tal.lua index debcedfd3..63a66d037 100644 --- a/tex/context/base/typo-tal.lua +++ b/tex/context/base/typo-tal.lua @@ -20,34 +20,19 @@ local fontcharacters = fonts.hashes.characters local unicodes = fonts.hashes.unicodes local categories = characters.categories -- nd -local nuts = nodes.nuts -local tonut = nuts.tonut -local tonode = nuts.tonode +local insert_node_before = nodes.insert_before +local insert_node_after = nodes.insert_after +local traverse_list_by_id = nodes.traverse_id +local dimensions_of_list = nodes.dimensions +local first_glyph = nodes.first_glyph -local getnext = nuts.getnext -local getprev = nuts.getprev -local getid = nuts.getid -local getfont = nuts.getfont -local getchar = nuts.getchar -local getattr = nuts.getattr -local getfield = nuts.getfield - -local setattr = nuts.setattr -local setfield = nuts.setfield - -local insert_node_before = nuts.insert_before -local insert_node_after = nuts.insert_after -local traverse_list_by_id = nuts.traverse_id -local dimensions_of_list = nuts.dimensions -local first_glyph = nuts.first_glyph - -local nodepool = nuts.pool +local nodepool = nodes.pool local new_kern = nodepool.kern local new_gluespec = nodepool.gluespec local tracers = nodes.tracers local setcolor = tracers.colors.set -local tracedrule = tracers.pool.nuts.rule +local tracedrule = tracers.pool.nodes.rule local characteralign = { } typesetters.characteralign = characteralign @@ -84,11 +69,10 @@ local function traced_kern(w) return tracedrule(w,nil,nil,"darkgray") end -function characteralign.handler(originalhead,where) +function characteralign.handler(head,where) if not datasets then - return originalhead, false + return head, false end - local head = tonut(originalhead) -- local first = first_glyph(head) -- we could do that once local first for n in traverse_list_by_id(glyph_code,head) do @@ -96,11 +80,11 @@ function characteralign.handler(originalhead,where) break end if not first then - return originalhead, false + return head, false end - local a = getattr(first,a_characteralign) + local a = first[a_characteralign] if not a or a == 0 then - return originalhead, false + return head, false end local column = div(a,100) local row = a % 100 @@ -116,10 +100,10 @@ function characteralign.handler(originalhead,where) local sign = nil -- we can think of constraints while current do - local id = getid(current) + local id = current.id if id == glyph_code then - local char = getchar(current) - local font = getfont(current) + local char = current.char + local font = current.font local unicode = unicodes[font][char] if not unicode then -- no unicode so forget about it @@ -142,13 +126,13 @@ function characteralign.handler(originalhead,where) if not b_start then if sign then b_start = sign - local new = validsigns[getchar(sign)] - if char == new or not fontcharacters[getfont(sign)][new] then + local new = validsigns[sign.char] + if char == new or not fontcharacters[sign.font][new] then if trace_split then setcolor(sign,"darkyellow") end else - setfield(sign,"char",new) + sign.char = new if trace_split then setcolor(sign,"darkmagenta") end @@ -174,14 +158,14 @@ function characteralign.handler(originalhead,where) end elseif (b_start or a_start) and id == glue_code then -- somewhat inefficient - local next = getnext(current) - local prev = getprev(current) - if next and prev and getid(next) == glyph_code and getid(prev) == glyph_code then -- too much checking - local width = fontcharacters[getfont(b_start)][separator or period].width - -- local spec = getfield(current,"spec") - -- free_spec(spec) - setfield(current,"spec",new_gluespec(width)) - setattr(current,a_character,punctuationspace) + local next = current.next + local prev = current.prev + if next and prev and next.id == glyph_code and prev.id == glyph_code then -- too much checking + local width = fontcharacters[b_start.font][separator or period].width + -- local spec = current.spec + -- nodes.free(spec) -- hm, we leak but not that many specs + current.spec = new_gluespec(width) + current[a_character] = punctuationspace if a_start then a_stop = current elseif b_start then @@ -189,7 +173,7 @@ function characteralign.handler(originalhead,where) end end end - current = getnext(current) + current = current.next end local entry = list[row] if entry then @@ -223,7 +207,7 @@ function characteralign.handler(originalhead,where) if not c then -- print("[before]") if dataset.hasseparator then - local width = fontcharacters[getfont(b_stop)][separator].width + local width = fontcharacters[b_stop.font][separator].width insert_node_after(head,b_stop,new_kern(maxafter+width)) end elseif a_start then @@ -245,7 +229,7 @@ function characteralign.handler(originalhead,where) end else -- print("[after]") - local width = fontcharacters[getfont(b_stop)][separator].width + local width = fontcharacters[b_stop.font][separator].width head = insert_node_before(head,a_start,new_kern(maxbefore+width)) end if after < maxafter then @@ -262,12 +246,12 @@ function characteralign.handler(originalhead,where) end else entry = { - before = b_start and dimensions_of_list(b_start,getnext(b_stop)) or 0, - after = a_start and dimensions_of_list(a_start,getnext(a_stop)) or 0, + before = b_start and dimensions_of_list(b_start,b_stop.next) or 0, + after = a_start and dimensions_of_list(a_start,a_stop.next) or 0, } list[row] = entry end - return tonode(head), true + return head, true end function setcharacteralign(column,separator) diff --git a/tex/context/base/util-deb.lua b/tex/context/base/util-deb.lua index ee732b3b5..785373f86 100644 --- a/tex/context/base/util-deb.lua +++ b/tex/context/base/util-deb.lua @@ -92,41 +92,37 @@ end function debugger.disable() debug.sethook() - -- counters[debug.getinfo(2,"f").func] = nil +--~ counters[debug.getinfo(2,"f").func] = nil end --- debugger.enable() --- --- print(math.sin(1*.5)) --- print(math.sin(1*.5)) --- print(math.sin(1*.5)) --- print(math.sin(1*.5)) --- print(math.sin(1*.5)) --- --- debugger.disable() --- --- print("") --- debugger.showstats() --- print("") --- debugger.showstats(print,3) --- +--~ debugger.enable() + +--~ print(math.sin(1*.5)) +--~ print(math.sin(1*.5)) +--~ print(math.sin(1*.5)) +--~ print(math.sin(1*.5)) +--~ print(math.sin(1*.5)) + +--~ debugger.disable() + +--~ print("") +--~ debugger.showstats() +--~ print("") +--~ debugger.showstats(print,3) + -- from the lua book: -local function showtraceback(rep) -- from lua site / adapted - local level = 2 -- we don't want this function to be reported - local reporter = rep or report +function traceback() + local level = 1 while true do - local info = getinfo(level, "Sl") + local info = debug.getinfo(level, "Sl") if not info then break elseif info.what == "C" then - reporter("%2i : %s",level-1,"C function") + print(format("%3i : C function",level)) else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) + print(format("%3i : [%s]:%d",level,info.short_src,info.currentline)) end level = level + 1 end end - -debugger.showtraceback = showtraceback --- debug.showtraceback = showtraceback diff --git a/tex/context/base/util-str.lua b/tex/context/base/util-str.lua index 4ecaed7d3..af8b1651e 100644 --- a/tex/context/base/util-str.lua +++ b/tex/context/base/util-str.lua @@ -20,24 +20,8 @@ local utfchar, utfbyte = utf.char, utf.byte ----- loadstripped = utilities.lua.loadstripped ----- setmetatableindex = table.setmetatableindex -local loadstripped = nil - -if _LUAVERSION < 5.2 then - - loadstripped = function(str,shortcuts) - return load(str) - end - -else - - loadstripped = function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end - +local loadstripped = _LUAVERSION < 5.2 and load or function(str) + return load(dump(load(str),true)) -- it only makes sense in luajit and luatex where we have a stipped load end -- todo: make a special namespace for the formatter @@ -307,67 +291,33 @@ function number.sparseexponent(f,n) return tostring(n) end +local preamble = [[ +local type = type +local tostring = tostring +local tonumber = tonumber +local format = string.format +local concat = table.concat +local signed = number.signed +local points = number.points +local basepoints = number.basepoints +local utfchar = utf.char +local utfbyte = utf.byte +local lpegmatch = lpeg.match +local nspaces = string.nspaces +local tracedchar = string.tracedchar +local autosingle = string.autosingle +local autodouble = string.autodouble +local sequenced = table.sequenced +local formattednumber = number.formatted +local sparseexponent = number.sparseexponent +]] + local template = [[ %s %s return function(%s) return %s end ]] -local preamble, environment = "", { } - -if _LUAVERSION < 5.2 then - - preamble = [[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] - -else - - environment = { - global = global or _G, - lpeg = lpeg, - type = type, - tostring = tostring, - tonumber = tonumber, - format = string.format, - concat = table.concat, - signed = number.signed, - points = number.points, - basepoints = number.basepoints, - utfchar = utf.char, - utfbyte = utf.byte, - lpegmatch = lpeg.match, - nspaces = string.nspaces, - tracedchar = string.tracedchar, - autosingle = string.autosingle, - autodouble = string.autodouble, - sequenced = table.sequenced, - formattednumber = number.formatted, - sparseexponent = number.sparseexponent, - } - -end - --- -- -- - local arguments = { "a1" } -- faster than previously used (select(n,...)) setmetatable(arguments, { __index = @@ -790,37 +740,28 @@ local builder = Cs { "start", -- we can be clever and only alias what is needed --- local direct = Cs ( --- P("%")/"" --- * Cc([[local format = string.format return function(str) return format("%]]) --- * (S("+- .") + R("09"))^0 --- * S("sqidfgGeExXo") --- * Cc([[",str) end]]) --- * P(-1) --- ) - local direct = Cs ( - P("%") - * (S("+- .") + R("09"))^0 - * S("sqidfgGeExXo") - * P(-1) / [[local format = string.format return function(str) return format("%0",str) end]] -) + P("%")/"" + * Cc([[local format = string.format return function(str) return format("%]]) + * (S("+- .") + R("09"))^0 + * S("sqidfgGeExXo") + * Cc([[",str) end]]) + * P(-1) + ) local function make(t,str) local f local p local p = lpegmatch(direct,str) if p then - -- f = loadstripped(p)() - -- print("builder 1 >",p) f = loadstripped(p)() else n = 0 p = lpegmatch(builder,str,1,"..",t._extensions_) -- after this we know n if n > 0 then p = format(template,preamble,t._preamble_,arguments[n],p) - -- print("builder 2 >",p) - f = loadstripped(p,t._environment_)() -- t._environment is not populated (was experiment) +-- print("builder>",p) + f = loadstripped(p)() else f = function() return str end end @@ -875,26 +816,10 @@ strings.formatters = { } -- table (metatable) in which case we could better keep a count and -- clear that table when a threshold is reached -if _LUAVERSION < 5.2 then - - function strings.formatters.new() - local t = { _extensions_ = { }, _preamble_ = preamble, _environment_ = { }, _type_ = "formatter" } - setmetatable(t, { __index = make, __call = use }) - return t - end - -else - - function strings.formatters.new() - local e = { } -- better make a copy as we can overload - for k, v in next, environment do - e[k] = v - end - local t = { _extensions_ = { }, _preamble_ = "", _environment_ = e, _type_ = "formatter" } - setmetatable(t, { __index = make, __call = use }) - return t - end - +function strings.formatters.new() + local t = { _extensions_ = { }, _preamble_ = "", _type_ = "formatter" } + setmetatable(t, { __index = make, __call = use }) + return t end -- function strings.formatters.new() @@ -913,12 +838,8 @@ string.formatter = function(str,...) return formatters[str](...) end -- someti local function add(t,name,template,preamble) if type(t) == "table" and t._type_ == "formatter" then t._extensions_[name] = template or "%s" - if type(preamble) == "string" then + if preamble then t._preamble_ = preamble .. "\n" .. t._preamble_ -- so no overload ! - elseif type(preamble) == "table" then - for k, v in next, preamble do - t._environment_[k] = v - end end end end @@ -935,23 +856,9 @@ patterns.luaquoted = Cs(Cc('"') * ((1-S('"\n'))^1 + P('"')/'\\"' + P('\n')/'\\n" -- escaping by lpeg is faster for strings without quotes, slower on a string with quotes, but -- faster again when other q-escapables are found (the ones we don't need to escape) --- add(formatters,"xml", [[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) --- add(formatters,"tex", [[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) --- add(formatters,"lua", [[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) - -if _LUAVERSION < 5.2 then - - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") - -else - - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape }) - -end +add(formatters,"xml", [[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) +add(formatters,"tex", [[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) +add(formatters,"lua", [[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) -- -- yes or no: -- diff --git a/tex/context/base/util-tab.lua b/tex/context/base/util-tab.lua index d235520c4..ae44269bb 100644 --- a/tex/context/base/util-tab.lua +++ b/tex/context/base/util-tab.lua @@ -316,7 +316,7 @@ function table.fastserialize(t,prefix) -- not sorted -- only number and string indices (currently) - local r = { type(prefix) == "string" and prefix or "return" } + local r = { prefix or "return" } local m = 1 local function fastserialize(t,outer) -- no mixes @@ -376,6 +376,7 @@ function table.fastserialize(t,prefix) end return r end + return concat(fastserialize(t,true)) end diff --git a/tex/context/base/x-mathml.lua b/tex/context/base/x-mathml.lua index baf839ad8..cd60e756d 100644 --- a/tex/context/base/x-mathml.lua +++ b/tex/context/base/x-mathml.lua @@ -82,9 +82,8 @@ local o_replacements = { -- in main table -- [utfchar(0xF103C)] = "\\mmlleftdelimiter<", [utfchar(0xF1026)] = "\\mmlchar{38}", - [utfchar(0x02061)] = "", -- function applicator sometimes shows up in font -- [utfchar(0xF103E)] = "\\mmlleftdelimiter>", - -- [utfchar(0x000AF)] = '\\mmlchar{"203E}', -- 0x203E + } local simpleoperatorremapper = utf.remapper(o_replacements) @@ -480,7 +479,7 @@ end function mathml.mo(id) local str = xmlcontent(getid(id)) or "" local rep = gsub(str,"&.-;","") -- todo - context(simpleoperatorremapper(rep) or rep) + context(simpleoperatorremapper(rep)) end function mathml.mi(id) @@ -492,18 +491,13 @@ function mathml.mi(id) if n == 0 then -- nothing to do elseif n == 1 then - local first = str[1] - if type(first) == "string" then - local str = gsub(first,"&.-;","") -- bah - local rep = i_replacements[str] - if not rep then - rep = gsub(str,".",i_replacements) - end - context(rep) - -- context.mi(rep) - else - context.xmlflush(id) -- xmlsprint or so + local str = gsub(str[1],"&.-;","") -- bah + local rep = i_replacements[str] + if not rep then + rep = gsub(str,".",i_replacements) end + context(rep) + -- context.mi(rep) else context.xmlflush(id) -- xmlsprint or so end @@ -834,13 +828,3 @@ function mathml.cpolar_a(root) end context.right(false,")") end - --- crap .. maybe in char-def a mathml overload - -local mathmleq = { - [utfchar(0x00AF)] = utfchar(0x203E), -} - -function mathml.extensible(chr) - context(mathmleq[chr] or chr) -end diff --git a/tex/context/base/x-mathml.mkiv b/tex/context/base/x-mathml.mkiv index 5520dbbe6..ec8fd74e4 100644 --- a/tex/context/base/x-mathml.mkiv +++ b/tex/context/base/x-mathml.mkiv @@ -2283,7 +2283,7 @@ \unexpanded\def\mmloverbs#1{\mmlexecuteifdefined\mmlbasecommand\relax{\mmlunexpandedsecond{#1}}\relax} \startxmlsetups mml:mover - \edef\mmlovertoken{\mmlextensible{\xmlraw{#1}{/mml:*[2]}}}% /text() + \edef\mmlovertoken{\xmlraw{#1}{/mml:*[2]}}% /text() \doifelseutfmathabove\mmlovertoken { \edef\mmlovercommand{\utfmathcommandabove\mmlovertoken} \mmloverof{#1} @@ -2295,7 +2295,7 @@ } { \edef\mmlbasecommand{\utfmathfiller\mmlbasetoken} \edef\mmlovercommand{\utfmathfiller\mmlovertoken} - \mmlundertriplet{\mmloverbf{#1}}{\mmloveros{#1}}{}%\relax + \mmlovertriplet{\mmloveros{#1}}{\mmloverbf{#1}}\relax } } % \limits % spoils spacing @@ -2321,18 +2321,13 @@ % % \limits % spoils spacing % \stopxmlsetups -% do this in lua - -\def\mmlextensible#1{\ctxmodulemathml{extensible(\!!bs#1\!!es)}} - \unexpanded\def\mmlunderuf#1{\mmlexecuteifdefined\mmlundercommand\relax {\mmlunexpandedfirst {#1}}\relax} \unexpanded\def\mmlunderus#1{\mmlexecuteifdefined\mmlundercommand {\mmlunexpandedsecond{#1}}\relax} \unexpanded\def\mmlunderbf#1{\mmlexecuteifdefined\mmlbasecommand {\mmlunexpandedfirst {#1}}\relax} -%unexpanded\def\mmlunderbs#1{\mmlexecuteifdefined\mmlbasecommand \relax{}{\mmlunexpandedsecond{#1}}\relax} -\unexpanded\def\mmlunderbs#1{\mmlexecuteifdefined\mmlbasecommand \relax {\mmlunexpandedsecond{#1}}\relax} +\unexpanded\def\mmlunderbs#1{\mmlexecuteifdefined\mmlbasecommand \relax{}{\mmlunexpandedsecond{#1}}\relax} \startxmlsetups mml:munder - \edef\mmlundertoken{\mmlextensible{\xmlraw{#1}{/mml:*[2]}}}% /text() + \edef\mmlundertoken{\xmlraw{#1}{/mml:*[2]}}% /text() \doifelseutfmathbelow\mmlundertoken {% \edef\mmlundercommand{\utfmathcommandbelow\mmlundertoken} \mmlunderuf{#1} @@ -2344,7 +2339,7 @@ } { \edef\mmlbasecommand {\utfmathfiller\mmlbasetoken} \edef\mmlundercommand{\utfmathfiller\mmlundertoken} - \mmlundertriplet{\mmlunderbf{#1}}{}{\mmlunderus{#1}}%\relax + \mmlundertriplet{\mmlunderus{#1}}{\mmlunderbf{#1}}\relax } } % \limits % spoils spacing diff --git a/tex/context/base/x-set-11.mkiv b/tex/context/base/x-set-11.mkiv index 12854dc92..d4b43a9ee 100644 --- a/tex/context/base/x-set-11.mkiv +++ b/tex/context/base/x-set-11.mkiv @@ -448,18 +448,8 @@ % \def\showsetupindeed#1% % {\xmlfilterlist{\loadedsetups}{interface/command[@name='#1']/command(xml:setups:typeset)}} -% \def\showsetupindeed#1% -% {\xmlfilterlist{\loadedsetups}{/interface/command['#1' == (@type=='environment' and 'start' or '') .. @name]/command(xml:setups:typeset)}} - -% \setelementnature[setup][display] -% \setelementnature[setup][mixed] - \def\showsetupindeed#1% - {\startelement[setup][name=#1]% - \startelement[noexport][comment={setup definition #1}] - \xmlfilterlist{\loadedsetups}{/interface/command['#1' == (@type=='environment' and 'start' or '') .. @name]/command(xml:setups:typeset)}% - \stopelement - \stopelement} + {\xmlfilterlist{\loadedsetups}{/interface/command['#1' == (@type=='environment' and 'start' or '') .. @name]/command(xml:setups:typeset)}} \unexpanded\def\placesetup {\placelistofsorts[texcommand][\c!criterium=\v!used]} \unexpanded\def\placeallsetups{\placelistofsorts[texcommand][\c!criterium=\v!all ]} @@ -648,16 +638,11 @@ \xmlflush{#1} \doifmode{interface:setup:defaults} { \ifx\currentSETUPhash\empty \else - \begingroup - % todo, make a one level expansion of parameter - \let\emwidth \relax - \let\exheight\relax - \edef\currentSETUPvalue{\csname named\currentSETUPhash parameter\endcsname\empty{\xmlatt{#1}{name}}} - \ifx\currentSETUPvalue\empty \else - =\space - \detokenize\expandafter{\currentSETUPvalue} - \fi - \endgroup + \edef\currentSETUPvalue{\csname named\currentSETUPhash parameter\endcsname\empty{\xmlatt{#1}{name}}} + \ifx\currentSETUPvalue\empty + \space=\space + \detokenize\expandafter{\currentSETUPvalue} + \fi \fi } \stopsecondSETUPcolumn @@ -833,6 +818,7 @@ \stoptabulate \stopxmlsetups + \starttexdefinition showrootvalues [#1] \edef\currentsetupparametercategory{#1} \edef\currentsetupparametercommand{setup#1} diff --git a/tex/context/interface/keys-cs.xml b/tex/context/interface/keys-cs.xml index 0a0b9b9a6..d36f969f3 100644 --- a/tex/context/interface/keys-cs.xml +++ b/tex/context/interface/keys-cs.xml @@ -1051,8 +1051,6 @@ <cd:constant name='suffix' value='suffix'/> <cd:constant name='suffixseparator' value='suffixseparator'/> <cd:constant name='suffixstopper' value='suffixstopper'/> - <cd:constant name='surnamefirstnamesep' value='surnamefirstnamesep'/> - <cd:constant name='surnameinitialsep' value='surnameinitialsep'/> <cd:constant name='surnamesep' value='surnamesep'/> <cd:constant name='sx' value='sx'/> <cd:constant name='sy' value='sy'/> diff --git a/tex/context/interface/keys-de.xml b/tex/context/interface/keys-de.xml index 28b21b915..c5ba364e3 100644 --- a/tex/context/interface/keys-de.xml +++ b/tex/context/interface/keys-de.xml @@ -1051,8 +1051,6 @@ <cd:constant name='suffix' value='suffix'/> <cd:constant name='suffixseparator' value='suffixseparator'/> <cd:constant name='suffixstopper' value='suffixstopper'/> - <cd:constant name='surnamefirstnamesep' value='surnamefirstnamesep'/> - <cd:constant name='surnameinitialsep' value='surnameinitialsep'/> <cd:constant name='surnamesep' value='surnamesep'/> <cd:constant name='sx' value='sx'/> <cd:constant name='sy' value='sy'/> diff --git a/tex/context/interface/keys-en.xml b/tex/context/interface/keys-en.xml index da433cdee..be59542e7 100644 --- a/tex/context/interface/keys-en.xml +++ b/tex/context/interface/keys-en.xml @@ -1051,8 +1051,6 @@ <cd:constant name='suffix' value='suffix'/> <cd:constant name='suffixseparator' value='suffixseparator'/> <cd:constant name='suffixstopper' value='suffixstopper'/> - <cd:constant name='surnamefirstnamesep' value='surnamefirstnamesep'/> - <cd:constant name='surnameinitialsep' value='surnameinitialsep'/> <cd:constant name='surnamesep' value='surnamesep'/> <cd:constant name='sx' value='sx'/> <cd:constant name='sy' value='sy'/> diff --git a/tex/context/interface/keys-fr.xml b/tex/context/interface/keys-fr.xml index 6a8eaa9c5..43c47d578 100644 --- a/tex/context/interface/keys-fr.xml +++ b/tex/context/interface/keys-fr.xml @@ -1051,8 +1051,6 @@ <cd:constant name='suffix' value='suffix'/> <cd:constant name='suffixseparator' value='suffixseparator'/> <cd:constant name='suffixstopper' value='suffixstopper'/> - <cd:constant name='surnamefirstnamesep' value='surnamefirstnamesep'/> - <cd:constant name='surnameinitialsep' value='surnameinitialsep'/> <cd:constant name='surnamesep' value='surnamesep'/> <cd:constant name='sx' value='sx'/> <cd:constant name='sy' value='sy'/> diff --git a/tex/context/interface/keys-it.xml b/tex/context/interface/keys-it.xml index c7c996318..95c2d8aa5 100644 --- a/tex/context/interface/keys-it.xml +++ b/tex/context/interface/keys-it.xml @@ -1051,8 +1051,6 @@ <cd:constant name='suffix' value='suffix'/> <cd:constant name='suffixseparator' value='suffixseparator'/> <cd:constant name='suffixstopper' value='suffixstopper'/> - <cd:constant name='surnamefirstnamesep' value='surnamefirstnamesep'/> - <cd:constant name='surnameinitialsep' value='surnameinitialsep'/> <cd:constant name='surnamesep' value='surnamesep'/> <cd:constant name='sx' value='sx'/> <cd:constant name='sy' value='sy'/> diff --git a/tex/context/interface/keys-nl.xml b/tex/context/interface/keys-nl.xml index 21536214a..bc940ebc4 100644 --- a/tex/context/interface/keys-nl.xml +++ b/tex/context/interface/keys-nl.xml @@ -1051,8 +1051,6 @@ <cd:constant name='suffix' value='suffix'/> <cd:constant name='suffixseparator' value='suffixscheider'/> <cd:constant name='suffixstopper' value='suffixafsluiter'/> - <cd:constant name='surnamefirstnamesep' value='surnamefirstnamesep'/> - <cd:constant name='surnameinitialsep' value='surnameinitialsep'/> <cd:constant name='surnamesep' value='surnamesep'/> <cd:constant name='sx' value='sx'/> <cd:constant name='sy' value='sy'/> diff --git a/tex/context/interface/keys-pe.xml b/tex/context/interface/keys-pe.xml index 8e4d412d5..75e3a17c2 100644 --- a/tex/context/interface/keys-pe.xml +++ b/tex/context/interface/keys-pe.xml @@ -1051,8 +1051,6 @@ <cd:constant name='suffix' value='پسوند'/> <cd:constant name='suffixseparator' value='suffixseparator'/> <cd:constant name='suffixstopper' value='suffixstopper'/> - <cd:constant name='surnamefirstnamesep' value='surnamefirstnamesep'/> - <cd:constant name='surnameinitialsep' value='surnameinitialsep'/> <cd:constant name='surnamesep' value='surnamesep'/> <cd:constant name='sx' value='sx'/> <cd:constant name='sy' value='sy'/> diff --git a/tex/context/interface/keys-ro.xml b/tex/context/interface/keys-ro.xml index f9ef01b9f..e83d145d0 100644 --- a/tex/context/interface/keys-ro.xml +++ b/tex/context/interface/keys-ro.xml @@ -1051,8 +1051,6 @@ <cd:constant name='suffix' value='suffix'/> <cd:constant name='suffixseparator' value='suffixseparator'/> <cd:constant name='suffixstopper' value='suffixstopper'/> - <cd:constant name='surnamefirstnamesep' value='surnamefirstnamesep'/> - <cd:constant name='surnameinitialsep' value='surnameinitialsep'/> <cd:constant name='surnamesep' value='surnamesep'/> <cd:constant name='sx' value='sx'/> <cd:constant name='sy' value='sy'/> diff --git a/tex/generic/context/luatex/luatex-fonts-inj.lua b/tex/generic/context/luatex/luatex-fonts-inj.lua deleted file mode 100644 index ae48150a6..000000000 --- a/tex/generic/context/luatex/luatex-fonts-inj.lua +++ /dev/null @@ -1,526 +0,0 @@ -if not modules then modules = { } end modules ['node-inj'] = { - version = 1.001, - comment = "companion to node-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - --- This is very experimental (this will change when we have luatex > .50 and --- a few pending thingies are available. Also, Idris needs to make a few more --- test fonts. Btw, future versions of luatex will have extended glyph properties --- that can be of help. Some optimizations can go away when we have faster machines. - --- todo: make a special one for context - -local next = next -local utfchar = utf.char - -local trace_injections = false trackers.register("nodes.injections", function(v) trace_injections = v end) - -local report_injections = logs.reporter("nodes","injections") - -local attributes, nodes, node = attributes, nodes, node - -fonts = fonts -local fontdata = fonts.hashes.identifiers - -nodes.injections = nodes.injections or { } -local injections = nodes.injections - -local nodecodes = nodes.nodecodes -local glyph_code = nodecodes.glyph -local kern_code = nodecodes.kern -local nodepool = nodes.pool -local newkern = nodepool.kern - -local traverse_id = node.traverse_id -local insert_node_before = node.insert_before -local insert_node_after = node.insert_after - -local a_kernpair = attributes.private('kernpair') -local a_ligacomp = attributes.private('ligacomp') -local a_markbase = attributes.private('markbase') -local a_markmark = attributes.private('markmark') -local a_markdone = attributes.private('markdone') -local a_cursbase = attributes.private('cursbase') -local a_curscurs = attributes.private('curscurs') -local a_cursdone = attributes.private('cursdone') - --- This injector has been tested by Idris Samawi Hamid (several arabic fonts as well as --- the rather demanding Husayni font), Khaled Hosny (latin and arabic) and Kaj Eigner --- (arabic, hebrew and thai) and myself (whatever font I come across). I'm pretty sure --- that this code is not 100% okay but examples are needed to figure things out. - -function injections.installnewkern(nk) - newkern = nk or newkern -end - -local cursives = { } -local marks = { } -local kerns = { } - --- Currently we do gpos/kern in a bit inofficial way but when we have the extra fields in --- glyphnodes to manipulate ht/dp/wd explicitly I will provide an alternative; also, we --- can share tables. - --- For the moment we pass the r2l key ... volt/arabtype tests .. idris: this needs --- checking with husayni (volt and fontforge). - -function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmnext) - local dx, dy = factor*(exit[1]-entry[1]), factor*(exit[2]-entry[2]) - local ws, wn = tfmstart.width, tfmnext.width - local bound = #cursives + 1 - start[a_cursbase] = bound - nxt[a_curscurs] = bound - cursives[bound] = { rlmode, dx, dy, ws, wn } - return dx, dy, bound -end - -function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr) - local x, y, w, h = factor*spec[1], factor*spec[2], factor*spec[3], factor*spec[4] - -- dy = y - h - if x ~= 0 or w ~= 0 or y ~= 0 or h ~= 0 then - local bound = current[a_kernpair] - if bound then - local kb = kerns[bound] - -- inefficient but singles have less, but weird anyway, needs checking - kb[2], kb[3], kb[4], kb[5] = (kb[2] or 0) + x, (kb[3] or 0) + y, (kb[4] or 0)+ w, (kb[5] or 0) + h - else - bound = #kerns + 1 - current[a_kernpair] = bound - kerns[bound] = { rlmode, x, y, w, h, r2lflag, tfmchr.width } - end - return x, y, w, h, bound - end - return x, y, w, h -- no bound -end - -function injections.setkern(current,factor,rlmode,x,tfmchr) - local dx = factor*x - if dx ~= 0 then - local bound = #kerns + 1 - current[a_kernpair] = bound - kerns[bound] = { rlmode, dx } - return dx, bound - else - return 0, 0 - end -end - -function injections.setmark(start,base,factor,rlmode,ba,ma,index,baseismark) -- ba=baseanchor, ma=markanchor - local dx, dy = factor*(ba[1]-ma[1]), factor*(ba[2]-ma[2]) -- the index argument is no longer used but when this - local bound = base[a_markbase] -- fails again we should pass it - local index = 1 - if bound then - local mb = marks[bound] - if mb then - -- if not index then index = #mb + 1 end - index = #mb + 1 - mb[index] = { dx, dy, rlmode } - start[a_markmark] = bound - start[a_markdone] = index - return dx, dy, bound - else - report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound) - end - end --- index = index or 1 - index = index or 1 - bound = #marks + 1 - base[a_markbase] = bound - start[a_markmark] = bound - start[a_markdone] = index - marks[bound] = { [index] = { dx, dy, rlmode, baseismark } } - return dx, dy, bound -end - -local function dir(n) - return (n and n<0 and "r-to-l") or (n and n>0 and "l-to-r") or "unset" -end - -local function trace(head) - report_injections("begin run") - for n in traverse_id(glyph_code,head) do - if n.subtype < 256 then - local kp = n[a_kernpair] - local mb = n[a_markbase] - local mm = n[a_markmark] - local md = n[a_markdone] - local cb = n[a_cursbase] - local cc = n[a_curscurs] - local char = n.char - report_injections("font %s, char %U, glyph %c",n.font,char,char) - if kp then - local k = kerns[kp] - if k[3] then - report_injections(" pairkern: dir %a, x %p, y %p, w %p, h %p",dir(k[1]),k[2],k[3],k[4],k[5]) - else - report_injections(" kern: dir %a, dx %p",dir(k[1]),k[2]) - end - end - if mb then - report_injections(" markbase: bound %a",mb) - end - if mm then - local m = marks[mm] - if mb then - local m = m[mb] - if m then - report_injections(" markmark: bound %a, index %a, dx %p, dy %p",mm,md,m[1],m[2]) - else - report_injections(" markmark: bound %a, missing index",mm) - end - else - m = m[1] - report_injections(" markmark: bound %a, dx %p, dy %p",mm,m and m[1],m and m[2]) - end - end - if cb then - report_injections(" cursbase: bound %a",cb) - end - if cc then - local c = cursives[cc] - report_injections(" curscurs: bound %a, dir %a, dx %p, dy %p",cc,dir(c[1]),c[2],c[3]) - end - end - end - report_injections("end run") -end - --- todo: reuse tables (i.e. no collection), but will be extra fields anyway --- todo: check for attribute - --- We can have a fast test on a font being processed, so we can check faster for marks etc --- but I'll make a context variant anyway. - -local function show_result(head) - local current = head - local skipping = false - while current do - local id = current.id - if id == glyph_code then - report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset) - skipping = false - elseif id == kern_code then - report_injections("kern: %p",current.kern) - skipping = false - elseif not skipping then - report_injections() - skipping = true - end - current = current.next - end -end - -function injections.handler(head,where,keep) - local has_marks, has_cursives, has_kerns = next(marks), next(cursives), next(kerns) - if has_marks or has_cursives then - if trace_injections then - trace(head) - end - -- in the future variant we will not copy items but refs to tables - local done, ky, rl, valid, cx, wx, mk, nofvalid = false, { }, { }, { }, { }, { }, { }, 0 - if has_kerns then -- move outside loop - local nf, tm = nil, nil - for n in traverse_id(glyph_code,head) do -- only needed for relevant fonts - if n.subtype < 256 then - nofvalid = nofvalid + 1 - valid[nofvalid] = n - if n.font ~= nf then - nf = n.font - tm = fontdata[nf].resources.marks - end - if tm then - mk[n] = tm[n.char] - end - local k = n[a_kernpair] - if k then - local kk = kerns[k] - if kk then - local x, y, w, h = kk[2] or 0, kk[3] or 0, kk[4] or 0, kk[5] or 0 - local dy = y - h - if dy ~= 0 then - ky[n] = dy - end - if w ~= 0 or x ~= 0 then - wx[n] = kk - end - rl[n] = kk[1] -- could move in test - end - end - end - end - else - local nf, tm = nil, nil - for n in traverse_id(glyph_code,head) do - if n.subtype < 256 then - nofvalid = nofvalid + 1 - valid[nofvalid] = n - if n.font ~= nf then - nf = n.font - tm = fontdata[nf].resources.marks - end - if tm then - mk[n] = tm[n.char] - end - end - end - end - if nofvalid > 0 then - -- we can assume done == true because we have cursives and marks - local cx = { } - if has_kerns and next(ky) then - for n, k in next, ky do - n.yoffset = k - end - end - -- todo: reuse t and use maxt - if has_cursives then - local p_cursbase, p = nil, nil - -- since we need valid[n+1] we can also use a "while true do" - local t, d, maxt = { }, { }, 0 - for i=1,nofvalid do -- valid == glyphs - local n = valid[i] - if not mk[n] then - local n_cursbase = n[a_cursbase] - if p_cursbase then - local n_curscurs = n[a_curscurs] - if p_cursbase == n_curscurs then - local c = cursives[n_curscurs] - if c then - local rlmode, dx, dy, ws, wn = c[1], c[2], c[3], c[4], c[5] - if rlmode >= 0 then - dx = dx - ws - else - dx = dx + wn - end - if dx ~= 0 then - cx[n] = dx - rl[n] = rlmode - end - -- if rlmode and rlmode < 0 then - dy = -dy - -- end - maxt = maxt + 1 - t[maxt] = p - d[maxt] = dy - else - maxt = 0 - end - end - elseif maxt > 0 then - local ny = n.yoffset - for i=maxt,1,-1 do - ny = ny + d[i] - local ti = t[i] - ti.yoffset = ti.yoffset + ny - end - maxt = 0 - end - if not n_cursbase and maxt > 0 then - local ny = n.yoffset - for i=maxt,1,-1 do - ny = ny + d[i] - local ti = t[i] - ti.yoffset = ny - end - maxt = 0 - end - p_cursbase, p = n_cursbase, n - end - end - if maxt > 0 then - local ny = n.yoffset - for i=maxt,1,-1 do - ny = ny + d[i] - local ti = t[i] - ti.yoffset = ny - end - maxt = 0 - end - if not keep then - cursives = { } - end - end - if has_marks then - for i=1,nofvalid do - local p = valid[i] - local p_markbase = p[a_markbase] - if p_markbase then - local mrks = marks[p_markbase] - local nofmarks = #mrks - for n in traverse_id(glyph_code,p.next) do - local n_markmark = n[a_markmark] - if p_markbase == n_markmark then - local index = n[a_markdone] or 1 - local d = mrks[index] - if d then - local rlmode = d[3] - -- - local k = wx[p] - if k then - local x = k[2] - local w = k[4] - if w then - if rlmode and rlmode >= 0 then - -- kern(x) glyph(p) kern(w-x) mark(n) - n.xoffset = p.xoffset - p.width + d[1] - (w-x) - else - -- kern(w-x) glyph(p) kern(x) mark(n) - n.xoffset = p.xoffset - d[1] - x - end - else - if rlmode and rlmode >= 0 then - -- okay for husayni - n.xoffset = p.xoffset - p.width + d[1] - else - -- needs checking: is x ok here? - n.xoffset = p.xoffset - d[1] - x - end - end - else - if rlmode and rlmode >= 0 then - n.xoffset = p.xoffset - p.width + d[1] - else - n.xoffset = p.xoffset - d[1] - end - local w = n.width - if w ~= 0 then - insert_node_before(head,n,newkern(-w/2)) - insert_node_after(head,n,newkern(-w/2)) - end - end - -- -- - if mk[p] then - n.yoffset = p.yoffset + d[2] - else - n.yoffset = n.yoffset + p.yoffset + d[2] - end - -- - if nofmarks == 1 then - break - else - nofmarks = nofmarks - 1 - end - end - else - -- KE: there can be <mark> <mkmk> <mark> sequences in ligatures - end - end - end - end - if not keep then - marks = { } - end - end - -- todo : combine - if next(wx) then - for n, k in next, wx do - -- only w can be nil (kernclasses), can be sped up when w == nil - local x = k[2] - local w = k[4] - if w then - local rl = k[1] -- r2l = k[6] - local wx = w - x - if rl < 0 then -- KE: don't use r2l here - if wx ~= 0 then - insert_node_before(head,n,newkern(wx)) -- type 0/2 - end - if x ~= 0 then - insert_node_after (head,n,newkern(x)) -- type 0/2 - end - else - if x ~= 0 then - insert_node_before(head,n,newkern(x)) -- type 0/2 - end - if wx ~= 0 then - insert_node_after (head,n,newkern(wx)) -- type 0/2 - end - end - elseif x ~= 0 then - -- this needs checking for rl < 0 but it is unlikely that a r2l script - -- uses kernclasses between glyphs so we're probably safe (KE has a - -- problematic font where marks interfere with rl < 0 in the previous - -- case) - insert_node_before(head,n,newkern(x)) -- a real font kern, type 0 - end - end - end - if next(cx) then - for n, k in next, cx do - if k ~= 0 then - local rln = rl[n] - if rln and rln < 0 then - insert_node_before(head,n,newkern(-k)) -- type 0/2 - else - insert_node_before(head,n,newkern(k)) -- type 0/2 - end - end - end - end - if not keep then - kerns = { } - end - -- if trace_injections then - -- show_result(head) - -- end - return head, true - elseif not keep then - kerns, cursives, marks = { }, { }, { } - end - elseif has_kerns then - if trace_injections then - trace(head) - end - for n in traverse_id(glyph_code,head) do - if n.subtype < 256 then - local k = n[a_kernpair] - if k then - local kk = kerns[k] - if kk then - local rl, x, y, w = kk[1], kk[2] or 0, kk[3], kk[4] - if y and y ~= 0 then - n.yoffset = y -- todo: h ? - end - if w then - -- copied from above - -- local r2l = kk[6] - local wx = w - x - if rl < 0 then -- KE: don't use r2l here - if wx ~= 0 then - insert_node_before(head,n,newkern(wx)) - end - if x ~= 0 then - insert_node_after (head,n,newkern(x)) - end - else - if x ~= 0 then - insert_node_before(head,n,newkern(x)) - end - if wx ~= 0 then - insert_node_after(head,n,newkern(wx)) - end - end - else - -- simple (e.g. kernclass kerns) - if x ~= 0 then - insert_node_before(head,n,newkern(x)) - end - end - end - end - end - end - if not keep then - kerns = { } - end - -- if trace_injections then - -- show_result(head) - -- end - return head, true - else - -- no tracing needed - end - return head, false -end diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 3f408b96f..24e49308c 100644 --- a/tex/generic/context/luatex/luatex-fonts-merged.lua +++ b/tex/generic/context/luatex/luatex-fonts-merged.lua @@ -1,6 +1,6 @@ -- merged file : luatex-fonts-merged.lua -- parent file : luatex-fonts.lua --- merge date : 02/14/14 17:07:59 +-- merge date : 01/03/14 00:40:35 do -- begin closure to overcome local limits and interference @@ -82,9 +82,6 @@ function optionalrequire(...) return result end end -if lua then - lua.mask=load([[τεχ = 1]]) and "utf" or "ascii" -end end -- closure @@ -104,9 +101,7 @@ local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.forma local floor=math.floor local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print -if setinspector then - setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) -end +setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end) lpeg.patterns=lpeg.patterns or {} local patterns=lpeg.patterns local anything=P(1) @@ -175,11 +170,9 @@ patterns.spacer=spacer patterns.whitespace=whitespace patterns.nonspacer=nonspacer patterns.nonwhitespace=nonwhitespace -local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) -local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0) +local stripper=spacer^0*C((spacer^0*nonspacer^1)^0) local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0)) patterns.stripper=stripper -patterns.fullstripper=fullstripper patterns.collapser=collapser patterns.lowercase=lowercase patterns.uppercase=uppercase @@ -402,7 +395,7 @@ function lpeg.replacer(one,two,makefunction,isutf) return pattern end end -function lpeg.finder(lst,makefunction,isutf) +function lpeg.finder(lst,makefunction) local pattern if type(lst)=="table" then pattern=P(false) @@ -418,11 +411,7 @@ function lpeg.finder(lst,makefunction,isutf) else pattern=P(lst) end - if isutf then - pattern=((utf8char or 1)-pattern)^0*pattern - else - pattern=(1-pattern)^0*pattern - end + pattern=(1-pattern)^0*pattern if makefunction then return function(str) return lpegmatch(pattern,str) @@ -759,15 +748,11 @@ function string.limit(str,n,sentinel) end end local stripper=patterns.stripper -local fullstripper=patterns.fullstripper local collapser=patterns.collapser local longtostring=patterns.longtostring function string.strip(str) return lpegmatch(stripper,str) or "" end -function string.fullstrip(str) - return lpegmatch(fullstripper,str) or "" -end function string.collapsespaces(str) return lpegmatch(collapser,str) or "" end @@ -1651,9 +1636,7 @@ function table.print(t,...) serialize(print,t,...) end end -if setinspector then - setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) -end +setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) function table.sub(t,i,j) return { unpack(t,i,j) } end @@ -2525,19 +2508,8 @@ local unpack,concat=table.unpack,table.concat local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc local patterns,lpegmatch=lpeg.patterns,lpeg.match local utfchar,utfbyte=utf.char,utf.byte -local loadstripped=nil -if _LUAVERSION<5.2 then - loadstripped=function(str,shortcuts) - return load(str) - end -else - loadstripped=function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end - end +local loadstripped=_LUAVERSION<5.2 and load or function(str) + return load(dump(load(str),true)) end if not number then number={} end local stripper=patterns.stripzeros @@ -2687,58 +2659,31 @@ function number.sparseexponent(f,n) end return tostring(n) end +local preamble=[[ +local type = type +local tostring = tostring +local tonumber = tonumber +local format = string.format +local concat = table.concat +local signed = number.signed +local points = number.points +local basepoints = number.basepoints +local utfchar = utf.char +local utfbyte = utf.byte +local lpegmatch = lpeg.match +local nspaces = string.nspaces +local tracedchar = string.tracedchar +local autosingle = string.autosingle +local autodouble = string.autodouble +local sequenced = table.sequenced +local formattednumber = number.formatted +local sparseexponent = number.sparseexponent +]] local template=[[ %s %s return function(%s) return %s end ]] -local preamble,environment="",{} -if _LUAVERSION<5.2 then - preamble=[[ -local lpeg=lpeg -local type=type -local tostring=tostring -local tonumber=tonumber -local format=string.format -local concat=table.concat -local signed=number.signed -local points=number.points -local basepoints= number.basepoints -local utfchar=utf.char -local utfbyte=utf.byte -local lpegmatch=lpeg.match -local nspaces=string.nspaces -local tracedchar=string.tracedchar -local autosingle=string.autosingle -local autodouble=string.autodouble -local sequenced=table.sequenced -local formattednumber=number.formatted -local sparseexponent=number.sparseexponent - ]] -else - environment={ - global=global or _G, - lpeg=lpeg, - type=type, - tostring=tostring, - tonumber=tonumber, - format=string.format, - concat=table.concat, - signed=number.signed, - points=number.points, - basepoints=number.basepoints, - utfchar=utf.char, - utfbyte=utf.byte, - lpegmatch=lpeg.match, - nspaces=string.nspaces, - tracedchar=string.tracedchar, - autosingle=string.autosingle, - autodouble=string.autodouble, - sequenced=table.sequenced, - formattednumber=number.formatted, - sparseexponent=number.sparseexponent, - } -end local arguments={ "a1" } setmetatable(arguments,{ __index=function(t,k) local v=t[k-1]..",a"..k @@ -3060,8 +3005,8 @@ local builder=Cs { "start", ["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension, } local direct=Cs ( - P("%")*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*P(-1)/[[local format = string.format return function(str) return format("%0",str) end]] -) + P("%")/""*Cc([[local format = string.format return function(str) return format("%]])*(S("+- .")+R("09"))^0*S("sqidfgGeExXo")*Cc([[",str) end]])*P(-1) + ) local function make(t,str) local f local p @@ -3073,7 +3018,7 @@ local function make(t,str) p=lpegmatch(builder,str,1,"..",t._extensions_) if n>0 then p=format(template,preamble,t._preamble_,arguments[n],p) - f=loadstripped(p,t._environment_)() + f=loadstripped(p)() else f=function() return str end end @@ -3085,22 +3030,10 @@ local function use(t,fmt,...) return t[fmt](...) end strings.formatters={} -if _LUAVERSION<5.2 then - function strings.formatters.new() - local t={ _extensions_={},_preamble_=preamble,_environment_={},_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end -else - function strings.formatters.new() - local e={} - for k,v in next,environment do - e[k]=v - end - local t={ _extensions_={},_preamble_="",_environment_=e,_type_="formatter" } - setmetatable(t,{ __index=make,__call=use }) - return t - end +function strings.formatters.new() + local t={ _extensions_={},_preamble_="",_type_="formatter" } + setmetatable(t,{ __index=make,__call=use }) + return t end local formatters=strings.formatters.new() string.formatters=formatters @@ -3108,12 +3041,8 @@ string.formatter=function(str,...) return formatters[str](...) end local function add(t,name,template,preamble) if type(t)=="table" and t._type_=="formatter" then t._extensions_[name]=template or "%s" - if type(preamble)=="string" then + if preamble then t._preamble_=preamble.."\n"..t._preamble_ - elseif type(preamble)=="table" then - for k,v in next,preamble do - t._environment_[k]=v - end end end end @@ -3122,15 +3051,9 @@ patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"" patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+P(1))^0) patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) -if _LUAVERSION<5.2 then - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape") - add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape") - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape") -else - add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape }) - add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape }) - add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape }) -end +add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],[[local xmlescape = lpeg.patterns.xmlescape]]) +add(formatters,"tex",[[lpegmatch(texescape,%s)]],[[local texescape = lpeg.patterns.texescape]]) +add(formatters,"lua",[[lpegmatch(luaescape,%s)]],[[local luaescape = lpeg.patterns.luaescape]]) end -- closure @@ -6482,7 +6405,7 @@ local type,next,tonumber,tostring=type,next,tonumber,tostring local abs=math.abs local insert=table.insert local lpegmatch=lpeg.match -local reversed,concat,remove,sortedkeys=table.reversed,table.concat,table.remove,table.sortedkeys +local reversed,concat,remove=table.reversed,table.concat,table.remove local ioflush=io.flush local fastcopy,tohash,derivetable=table.fastcopy,table.tohash,table.derive local formatters=string.formatters @@ -6504,7 +6427,7 @@ local report_otf=logs.reporter("fonts","otf loading") local fonts=fonts local otf=fonts.handlers.otf otf.glists={ "gsub","gpos" } -otf.version=2.751 +otf.version=2.749 otf.cache=containers.define("fonts","otf",otf.version,true) local fontdata=fonts.hashes.identifiers local chardata=characters and characters.data @@ -6656,7 +6579,6 @@ local valid_fields=table.tohash { "upos", "use_typo_metrics", "uwidth", - "validation_state", "version", "vert_base", "weight", @@ -7123,6 +7045,7 @@ actions["prepare glyphs"]=function(data,filename,raw) } local altuni=glyph.altuni if altuni then + local d for i=1,#altuni do local a=altuni[i] local u=a.unicode @@ -7135,8 +7058,15 @@ actions["prepare glyphs"]=function(data,filename,raw) vv={ [u]=unicode } variants[v]=vv end + elseif d then + d[#d+1]=u + else + d={ u } end end + if d then + duplicates[unicode]=d + end end else report_otf("potential problem: glyph %U is used but empty",index) @@ -7154,49 +7084,47 @@ actions["check encoding"]=function(data,filename,raw) local duplicates=resources.duplicates local mapdata=raw.map or {} local unicodetoindex=mapdata and mapdata.map or {} - local indextounicode=mapdata and mapdata.backmap or {} local encname=lower(data.enc_name or mapdata.enc_name or "") local criterium=0xFFFF if find(encname,"unicode") then if trace_loading then report_otf("checking embedded unicode map %a",encname) end - local hash={} - for index,unicode in next,indices do - hash[index]=descriptions[unicode] - end - local reported={} - for unicode,index in next,unicodetoindex do - if not descriptions[unicode] then - local d=hash[index] - if d then - if d.unicode~=unicode then - local c=d.copies - if c then - c[unicode]=true - else - d.copies={ [unicode]=true } + for unicode,index in next,unicodetoindex do + if unicode<=criterium and not descriptions[unicode] then + local parent=indices[index] + if not parent then + report_otf("weird, unicode %U points to nowhere with index %H",unicode,index) + else + local parentdescription=descriptions[parent] + if parentdescription then + local altuni=parentdescription.altuni + if not altuni then + altuni={ { unicode=unicode } } + parentdescription.altuni=altuni + duplicates[parent]={ unicode } + else + local done=false + for i=1,#altuni do + if altuni[i].unicode==unicode then + done=true + break + end end + if not done then + insert(altuni,{ unicode=unicode }) + insert(duplicates[parent],unicode) + end + end + if trace_loading then + report_otf("weird, unicode %U points to nowhere with index %H",unicode,index) end - elseif not reported[i] then - report_otf("missing index %i",index) - reported[i]=true + else + report_otf("weird, unicode %U points to %U with index %H",unicode,index) end end end - for index,data in next,hash do - data.copies=sortedkeys(data.copies) - end - for index,unicode in next,indices do - local description=hash[index] - local copies=description.copies - if copies then - duplicates[unicode]=copies - description.copies=nil - else - report_otf("copies but no unicode parent %U",unicode) - end - end + end elseif properties.cidinfo then report_otf("warning: no unicode map, used cidmap %a",properties.cidinfo.usedname) else @@ -7204,7 +7132,6 @@ actions["check encoding"]=function(data,filename,raw) end if mapdata then mapdata.map={} - mapdata.backmap={} end end actions["add duplicates"]=function(data,filename,raw) @@ -7215,37 +7142,28 @@ actions["add duplicates"]=function(data,filename,raw) local indices=resources.indices local duplicates=resources.duplicates for unicode,d in next,duplicates do - local nofduplicates=#d - if nofduplicates>4 then - if trace_loading then - report_otf("ignoring excessive duplicates of %U (n=%s)",unicode,nofduplicates) - end - else - for i=1,nofduplicates do - local u=d[i] - if not descriptions[u] then - local description=descriptions[unicode] - local n=0 - for _,description in next,descriptions do - if kerns then - local kerns=description.kerns - for _,k in next,kerns do - local ku=k[unicode] - if ku then - k[u]=ku - n=n+1 - end + for i=1,#d do + local u=d[i] + if not descriptions[u] then + local description=descriptions[unicode] + local duplicate=table.copy(description) + duplicate.comment=format("copy of U+%05X",unicode) + descriptions[u]=duplicate + local n=0 + for _,description in next,descriptions do + if kerns then + local kerns=description.kerns + for _,k in next,kerns do + local ku=k[unicode] + if ku then + k[u]=ku + n=n+1 end end end - if u>0 then - local duplicate=table.copy(description) - duplicate.comment=format("copy of U+%05X",unicode) - descriptions[u]=duplicate - if trace_loading then - report_otf("duplicating %U to %U with index %H (%s kerns)",unicode,u,description.index,n) - end - end + end + if trace_loading then + report_otf("duplicating %U to %U with index %H (%s kerns)",unicode,u,description.index,n) end end end @@ -7969,11 +7887,6 @@ actions["check metadata"]=function(data,filename,raw) ttftables[i].data="deleted" end end - if metadata.validation_state and table.contains(metadata.validation_state,"bad_ps_fontname") then - local name=file.nameonly(filename) - metadata.fontname="bad-fontname-"..name - metadata.fullname="bad-fullname-"..name - end end actions["cleanup tables"]=function(data,filename,raw) data.resources.indices=nil @@ -8271,24 +8184,6 @@ local function otftotfm(specification) local features=specification.features.normal local rawdata=otf.load(filename,sub,features and features.featurefile) if rawdata and next(rawdata) then - local descriptions=rawdata.descriptions - local duplicates=rawdata.resources.duplicates - if duplicates then - local nofduplicates,nofduplicated=0,0 - for parent,list in next,duplicates do - for i=1,#list do - local unicode=list[i] - if not descriptions[unicode] then - descriptions[unicode]=descriptions[parent] - nofduplicated=nofduplicated+1 - end - end - nofduplicates=nofduplicates+#list - end - if trace_otf and nofduplicated~=nofduplicates then - report_otf("%i extra duplicates copied out of %i",nofduplicated,nofduplicates) - end - end rawdata.lookuphash={} tfmdata=copytotfm(rawdata,cache_id) if tfmdata and next(tfmdata) then @@ -8986,12 +8881,26 @@ nodes.injections=nodes.injections or {} local injections=nodes.injections local nodecodes=nodes.nodecodes local glyph_code=nodecodes.glyph +local disc_code=nodecodes.disc local kern_code=nodecodes.kern -local nodepool=nodes.pool +local nuts=nodes.nuts +local nodepool=nuts.pool local newkern=nodepool.kern -local traverse_id=node.traverse_id -local insert_node_before=node.insert_before -local insert_node_after=node.insert_after +local tonode=nuts.tonode +local tonut=nuts.tonut +local getfield=nuts.getfield +local getnext=nuts.getnext +local getprev=nuts.getprev +local getid=nuts.getid +local getattr=nuts.getattr +local getfont=nuts.getfont +local getsubtype=nuts.getsubtype +local getchar=nuts.getchar +local setfield=nuts.setfield +local setattr=nuts.setattr +local traverse_id=nuts.traverse_id +local insert_node_before=nuts.insert_before +local insert_node_after=nuts.insert_after local a_kernpair=attributes.private('kernpair') local a_ligacomp=attributes.private('ligacomp') local a_markbase=attributes.private('markbase') @@ -9010,21 +8919,21 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne local dx,dy=factor*(exit[1]-entry[1]),factor*(exit[2]-entry[2]) local ws,wn=tfmstart.width,tfmnext.width local bound=#cursives+1 - start[a_cursbase]=bound - nxt[a_curscurs]=bound + setattr(start,a_cursbase,bound) + setattr(nxt,a_curscurs,bound) cursives[bound]={ rlmode,dx,dy,ws,wn } return dx,dy,bound end function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr) local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4] if x~=0 or w~=0 or y~=0 or h~=0 then - local bound=current[a_kernpair] + local bound=getattr(current,a_kernpair) if bound then local kb=kerns[bound] kb[2],kb[3],kb[4],kb[5]=(kb[2] or 0)+x,(kb[3] or 0)+y,(kb[4] or 0)+w,(kb[5] or 0)+h else bound=#kerns+1 - current[a_kernpair]=bound + setattr(current,a_kernpair,bound) kerns[bound]={ rlmode,x,y,w,h,r2lflag,tfmchr.width } end return x,y,w,h,bound @@ -9035,7 +8944,7 @@ function injections.setkern(current,factor,rlmode,x,tfmchr) local dx=factor*x if dx~=0 then local bound=#kerns+1 - current[a_kernpair]=bound + setattr(current,a_kernpair,bound) kerns[bound]={ rlmode,dx } return dx,bound else @@ -9044,25 +8953,25 @@ function injections.setkern(current,factor,rlmode,x,tfmchr) end function injections.setmark(start,base,factor,rlmode,ba,ma,index,baseismark) local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2]) - local bound=base[a_markbase] + local bound=getattr(base,a_markbase) local index=1 if bound then local mb=marks[bound] if mb then index=#mb+1 mb[index]={ dx,dy,rlmode } - start[a_markmark]=bound - start[a_markdone]=index + setattr(start,a_markmark,bound) + setattr(start,a_markdone,index) return dx,dy,bound else - report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound) + report_injections("possible problem, %U is base mark without data (id %a)",getchar(base),bound) end end index=index or 1 bound=#marks+1 - base[a_markbase]=bound - start[a_markmark]=bound - start[a_markdone]=index + setattr(base,a_markbase,bound) + setattr(start,a_markmark,bound) + setattr(start,a_markdone,index) marks[bound]={ [index]={ dx,dy,rlmode,baseismark } } return dx,dy,bound end @@ -9072,15 +8981,15 @@ end local function trace(head) report_injections("begin run") for n in traverse_id(glyph_code,head) do - if n.subtype<256 then - local kp=n[a_kernpair] - local mb=n[a_markbase] - local mm=n[a_markmark] - local md=n[a_markdone] - local cb=n[a_cursbase] - local cc=n[a_curscurs] - local char=n.char - report_injections("font %s, char %U, glyph %c",n.font,char,char) + if getsubtype(n)<256 then + local kp=getattr(n,a_kernpair) + local mb=getattr(n,a_markbase) + local mm=getattr(n,a_markmark) + local md=getattr(n,a_markdone) + local cb=getattr(n,a_cursbase) + local cc=getattr(n,a_curscurs) + local char=getchar(n) + report_injections("font %s, char %U, glyph %c",getfont(n),char,char) if kp then local k=kerns[kp] if k[3] then @@ -9121,21 +9030,23 @@ local function show_result(head) local current=head local skipping=false while current do - local id=current.id + local id=getid(current) if id==glyph_code then - report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset) + report_injections("char: %C, width %p, xoffset %p, yoffset %p", + getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset")) skipping=false elseif id==kern_code then - report_injections("kern: %p",current.kern) + report_injections("kern: %p",getfield(current,"kern")) skipping=false elseif not skipping then report_injections() skipping=true end - current=current.next + current=getnext(current) end end function injections.handler(head,where,keep) + head=tonut(head) local has_marks,has_cursives,has_kerns=next(marks),next(cursives),next(kerns) if has_marks or has_cursives then if trace_injections then @@ -9145,17 +9056,18 @@ function injections.handler(head,where,keep) if has_kerns then local nf,tm=nil,nil for n in traverse_id(glyph_code,head) do - if n.subtype<256 then + if getsubtype(n)<256 then nofvalid=nofvalid+1 valid[nofvalid]=n - if n.font~=nf then - nf=n.font - tm=fontdata[nf].resources.marks + local f=getfont(n) + if f~=nf then + nf=f + tm=fontdata[nf].resources.marks end if tm then - mk[n]=tm[n.char] + mk[n]=tm[getchar(n)] end - local k=n[a_kernpair] + local k=getattr(n,a_kernpair) if k then local kk=kerns[k] if kk then @@ -9175,15 +9087,16 @@ function injections.handler(head,where,keep) else local nf,tm=nil,nil for n in traverse_id(glyph_code,head) do - if n.subtype<256 then + if getsubtype(n)<256 then nofvalid=nofvalid+1 valid[nofvalid]=n - if n.font~=nf then - nf=n.font - tm=fontdata[nf].resources.marks + local f=getfont(n) + if f~=nf then + nf=f + tm=fontdata[nf].resources.marks end if tm then - mk[n]=tm[n.char] + mk[n]=tm[getchar(n)] end end end @@ -9192,7 +9105,7 @@ function injections.handler(head,where,keep) local cx={} if has_kerns and next(ky) then for n,k in next,ky do - n.yoffset=k + setfield(n,"yoffset",k) end end if has_cursives then @@ -9201,9 +9114,9 @@ function injections.handler(head,where,keep) for i=1,nofvalid do local n=valid[i] if not mk[n] then - local n_cursbase=n[a_cursbase] + local n_cursbase=getattr(n,a_cursbase) if p_cursbase then - local n_curscurs=n[a_curscurs] + local n_curscurs=getattr(n,a_curscurs) if p_cursbase==n_curscurs then local c=cursives[n_curscurs] if c then @@ -9226,20 +9139,20 @@ function injections.handler(head,where,keep) end end elseif maxt>0 then - local ny=n.yoffset + local ny=getfield(n,"yoffset") for i=maxt,1,-1 do ny=ny+d[i] local ti=t[i] - ti.yoffset=ti.yoffset+ny + setfield(ti,"yoffset",getfield(ti,"yoffset")+ny) end maxt=0 end if not n_cursbase and maxt>0 then - local ny=n.yoffset + local ny=getfield(n,"yoffset") for i=maxt,1,-1 do ny=ny+d[i] local ti=t[i] - ti.yoffset=ny + setfield(ti,"yoffset",ny) end maxt=0 end @@ -9247,11 +9160,11 @@ function injections.handler(head,where,keep) end end if maxt>0 then - local ny=n.yoffset + local ny=getfield(n,"yoffset") for i=maxt,1,-1 do ny=ny+d[i] local ti=t[i] - ti.yoffset=ny + setfield(ti,"yoffset",ny) end maxt=0 end @@ -9262,57 +9175,66 @@ function injections.handler(head,where,keep) if has_marks then for i=1,nofvalid do local p=valid[i] - local p_markbase=p[a_markbase] + local p_markbase=getattr(p,a_markbase) if p_markbase then local mrks=marks[p_markbase] local nofmarks=#mrks - for n in traverse_id(glyph_code,p.next) do - local n_markmark=n[a_markmark] + for n in traverse_id(glyph_code,getnext(p)) do + local n_markmark=getattr(n,a_markmark) if p_markbase==n_markmark then - local index=n[a_markdone] or 1 + local index=getattr(n,a_markdone) or 1 local d=mrks[index] if d then local rlmode=d[3] local k=wx[p] + local px=getfield(p,"xoffset") + local ox=0 if k then local x=k[2] local w=k[4] if w then if rlmode and rlmode>=0 then - n.xoffset=p.xoffset-p.width+d[1]-(w-x) + ox=px-getfield(p,"width")+d[1]-(w-x) else - n.xoffset=p.xoffset-d[1]-x + ox=px-d[1]-x end else if rlmode and rlmode>=0 then - n.xoffset=p.xoffset-p.width+d[1] + ox=px-getfield(p,"width")+d[1] else - n.xoffset=p.xoffset-d[1]-x + ox=px-d[1]-x end end else + local wp=getfield(p,"width") + local wn=getfield(n,"width") if rlmode and rlmode>=0 then - n.xoffset=p.xoffset-p.width+d[1] + ox=px-wp+d[1] else - n.xoffset=p.xoffset-d[1] + ox=px-d[1] end - local w=n.width - if w~=0 then - insert_node_before(head,n,newkern(-w/2)) - insert_node_after(head,n,newkern(-w/2)) + if wn~=0 then + insert_node_before(head,n,newkern(-wn/2)) + insert_node_after(head,n,newkern(-wn/2)) end end + setfield(n,"xoffset",ox) + local py=getfield(p,"yoffset") + local oy=0 if mk[p] then - n.yoffset=p.yoffset+d[2] + oy=py+d[2] else - n.yoffset=n.yoffset+p.yoffset+d[2] + oy=getfield(n,"yoffset")+py+d[2] end + setfield(n,"yoffset",oy) if nofmarks==1 then break else nofmarks=nofmarks-1 end end + elseif not n_markmark then + break else end end @@ -9364,6 +9286,7 @@ function injections.handler(head,where,keep) if not keep then kerns={} end +head=tonode(head) return head,true elseif not keep then kerns,cursives,marks={},{},{} @@ -9373,14 +9296,14 @@ function injections.handler(head,where,keep) trace(head) end for n in traverse_id(glyph_code,head) do - if n.subtype<256 then - local k=n[a_kernpair] + if getsubtype(n)<256 then + local k=getattr(n,a_kernpair) if k then local kk=kerns[k] if kk then local rl,x,y,w=kk[1],kk[2] or 0,kk[3],kk[4] if y and y~=0 then - n.yoffset=y + setfield(n,"yoffset",y) end if w then local wx=w-x @@ -9411,10 +9334,10 @@ function injections.handler(head,where,keep) if not keep then kerns={} end - return head,true + return tonode(head),true else end - return head,false + return tonode(head),false end end -- closure @@ -9829,12 +9752,25 @@ registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive") registertracker("otf.actions","otf.replacements,otf.positions") registertracker("otf.injections","nodes.injections") registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing") -local insert_node_after=node.insert_after -local delete_node=nodes.delete -local copy_node=node.copy -local find_node_tail=node.tail or node.slide -local flush_node_list=node.flush_list -local end_of_math=node.end_of_math +local nuts=nodes.nuts +local tonode=nuts.tonode +local tonut=nuts.tonut +local getfield=nuts.getfield +local getnext=nuts.getnext +local getprev=nuts.getprev +local getid=nuts.getid +local getattr=nuts.getattr +local getfont=nuts.getfont +local getsubtype=nuts.getsubtype +local getchar=nuts.getchar +local setfield=nuts.setfield +local setattr=nuts.setattr +local insert_node_after=nuts.insert_after +local delete_node=nuts.delete +local copy_node=nuts.copy +local find_node_tail=nuts.tail +local flush_node_list=nuts.flush_list +local end_of_math=nuts.end_of_math local setmetatableindex=table.setmetatableindex local zwnj=0x200C local zwj=0x200D @@ -9945,83 +9881,83 @@ local function pref(kind,lookupname) return formatters["feature %a, lookup %a"](kind,lookupname) end local function copy_glyph(g) - local components=g.components + local components=getfield(g,"components") if components then - g.components=nil + setfield(g,"components",nil) local n=copy_node(g) - g.components=components + setfield(g,"components",components) return n else return copy_node(g) end end local function markstoligature(kind,lookupname,head,start,stop,char) - if start==stop and start.char==char then + if start==stop and getchar(start)==char then return head,start else - local prev=start.prev - local next=stop.next - start.prev=nil - stop.next=nil + local prev=getprev(start) + local next=getnext(stop) + setfield(start,"prev",nil) + setfield(stop,"next",nil) local base=copy_glyph(start) if head==start then head=base end - base.char=char - base.subtype=ligature_code - base.components=start + setfield(base,"char",char) + setfield(base,"subtype",ligature_code) + setfield(base,"components",start) if prev then - prev.next=base + setfield(prev,"next",base) end if next then - next.prev=base + setfield(next,"prev",base) end - base.next=next - base.prev=prev + setfield(base,"next",next) + setfield(base,"prev",prev) return head,base end end local function getcomponentindex(start) - if start.id~=glyph_code then + if getid(start)~=glyph_code then return 0 - elseif start.subtype==ligature_code then + elseif getsubtype(start)==ligature_code then local i=0 - local components=start.components + local components=getfield(start,"components") while components do i=i+getcomponentindex(components) - components=components.next + components=getnext(components) end return i - elseif not marks[start.char] then + elseif not marks[getchar(start)] then return 1 else return 0 end end local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) - if start==stop and start.char==char then - start.char=char + if start==stop and getchar(start)==char then + setfield(start,"char",char) return head,start end - local prev=start.prev - local next=stop.next - start.prev=nil - stop.next=nil + local prev=getprev(start) + local next=getnext(stop) + setfield(start,"prev",nil) + setfield(stop,"next",nil) local base=copy_glyph(start) if start==head then head=base end - base.char=char - base.subtype=ligature_code - base.components=start + setfield(base,"char",char) + setfield(base,"subtype",ligature_code) + setfield(base,"components",start) if prev then - prev.next=base + setfield(prev,"next",base) end if next then - next.prev=base + setfield(next,"prev",base) end - base.next=next - base.prev=prev + setfield(base,"next",next) + setfield(base,"prev",prev) if not discfound then local deletemarks=markflag~="mark" local components=start @@ -10030,42 +9966,42 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun local head=base local current=base while start do - local char=start.char + local char=getchar(start) if not marks[char] then baseindex=baseindex+componentindex componentindex=getcomponentindex(start) elseif not deletemarks then - start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex) + setattr(start,a_ligacomp,baseindex+(getattr(start,a_ligacomp) or componentindex)) if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) + logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp)) end head,current=insert_node_after(head,current,copy_node(start)) elseif trace_marks then logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char)) end - start=start.next + start=getnext(start) end - local start=current.next - while start and start.id==glyph_code do - local char=start.char + local start=getnext(current) + while start and getid(start)==glyph_code do + local char=getchar(start) if marks[char] then - start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex) + setattr(start,a_ligacomp,baseindex+(getattr(start,a_ligacomp) or componentindex)) if trace_marks then - logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) + logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp)) end else break end - start=start.next + start=getnext(start) end end return head,base end function handlers.gsub_single(head,start,kind,lookupname,replacement) if trace_singles then - logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement)) + logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement)) end - start.char=replacement + setfield(start,"char",replacement) return head,start,true end local function get_alternative_glyph(start,alternatives,value,trace_alternatives) @@ -10091,7 +10027,7 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives return false,trace_alternatives and formatters["invalid value %a, %s"](value,"out of range") end elseif value==0 then - return start.char,trace_alternatives and formatters["invalid value %a, %s"](value,"no change") + return getchar(start),trace_alternatives and formatters["invalid value %a, %s"](value,"no change") elseif value<1 then return alternatives[1],trace_alternatives and formatters["invalid value %a, taking %a"](value,1) else @@ -10102,25 +10038,25 @@ end local function multiple_glyphs(head,start,multiple,ignoremarks) local nofmultiples=#multiple if nofmultiples>0 then - start.char=multiple[1] + setfield(start,"char",multiple[1]) if nofmultiples>1 then - local sn=start.next + local sn=getnext(start) for k=2,nofmultiples do local n=copy_node(start) - n.char=multiple[k] - n.next=sn - n.prev=start + setfield(n,"char",multiple[k]) + setfield(n,"next",sn) + setfield(n,"prev",start) if sn then - sn.prev=n + setfield(sn,"prev",n) end - start.next=n + setfield(start,"next",n) start=n end end return head,start,true else if trace_multiples then - logprocess("no multiple for %s",gref(start.char)) + logprocess("no multiple for %s",gref(getchar(start))) end return head,start,false end @@ -10130,34 +10066,34 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence local choice,comment=get_alternative_glyph(start,alternative,value,trace_alternatives) if choice then if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(start.char),choice,gref(choice),comment) + logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment) end - start.char=choice + setfield(start,"char",choice) else if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(start.char),comment) + logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment) end end return head,start,true end function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence) if trace_multiples then - logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple)) + logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple)) end return multiple_glyphs(head,start,multiple,sequence.flags[1]) end function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) - local s,stop,discfound=start.next,nil,false - local startchar=start.char + local s,stop,discfound=getnext(start),nil,false + local startchar=getchar(start) if marks[startchar] then while s do - local id=s.id - if id==glyph_code and s.font==currentfont and s.subtype<256 then - local lg=ligature[s.char] + local id=getid(s) + if id==glyph_code and getfont(s)==currentfont and getsubtype(s)<256 then + local lg=ligature[getchar(s)] if lg then stop=s ligature=lg - s=s.next + s=getnext(s) else break end @@ -10169,9 +10105,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) local lig=ligature.ligature if lig then if trace_ligatures then - local stopchar=stop.char + local stopchar=getchar(stop) head,start=markstoligature(kind,lookupname,head,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start))) else head,start=markstoligature(kind,lookupname,head,start,stop,lig) end @@ -10182,18 +10118,18 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) else local skipmark=sequence.flags[1] while s do - local id=s.id - if id==glyph_code and s.subtype<256 then - if s.font==currentfont then - local char=s.char + local id=getid(s) + if id==glyph_code and getsubtype(s)<256 then + if getfont(s)==currentfont then + local char=getchar(s) if skipmark and marks[char] then - s=s.next + s=getnext(s) else local lg=ligature[char] if lg then stop=s ligature=lg - s=s.next + s=getnext(s) else break end @@ -10203,7 +10139,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) end elseif id==disc_code then discfound=true - s=s.next + s=getnext(s) else break end @@ -10212,36 +10148,35 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) if lig then if stop then if trace_ligatures then - local stopchar=stop.char + local stopchar=getchar(stop) head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) + logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start))) else head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound) end - return head,start,true else - start.char=lig + setfield(start,"char",lig) if trace_ligatures then logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig)) end - return head,start,true end + return head,start,true else end end return head,start,false end function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then - local base=start.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + local base=getprev(start) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) if marks[basechar] then while true do - base=base.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - basechar=base.char + base=getprev(base) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + basechar=getchar(base) if not marks[basechar] then break end @@ -10290,16 +10225,16 @@ function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence return head,start,false end function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then - local base=start.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + local base=getprev(start) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) if marks[basechar] then while true do - base=base.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - basechar=base.char + base=getprev(base) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + basechar=getchar(base) if not marks[basechar] then break end @@ -10311,7 +10246,7 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ end end end - local index=start[a_ligacomp] + local index=getattr(start,a_ligacomp) local baseanchors=descriptions[basechar] if baseanchors then baseanchors=baseanchors.anchors @@ -10356,22 +10291,22 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ return head,start,false end function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then - local base=start.prev - local slc=start[a_ligacomp] + local base=getprev(start) + local slc=getattr(start,a_ligacomp) if slc then while base do - local blc=base[a_ligacomp] + local blc=getattr(base,a_ligacomp) if blc and blc~=slc then - base=base.prev + base=getprev(base) else break end end end - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) local baseanchors=descriptions[basechar] if baseanchors then baseanchors=baseanchors.anchors @@ -10409,20 +10344,20 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence return head,start,false end function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) - local alreadydone=cursonce and start[a_cursbase] + local alreadydone=cursonce and getattr(start,a_cursbase) if not alreadydone then local done=false - local startchar=start.char + local startchar=getchar(start) if marks[startchar] then if trace_cursive then logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar)) end else - local nxt=start.next - while not done and nxt and nxt.id==glyph_code and nxt.font==currentfont and nxt.subtype<256 do - local nextchar=nxt.char + local nxt=getnext(start) + while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do + local nextchar=getchar(nxt) if marks[nextchar] then - nxt=nxt.next + nxt=getnext(nxt) else local entryanchors=descriptions[nextchar] if entryanchors then @@ -10456,13 +10391,13 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) return head,start,done else if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) + logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone) end return head,start,false end end function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence) - local startchar=start.char + local startchar=getchar(start) local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar]) if trace_kerns then logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h) @@ -10470,33 +10405,33 @@ function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence) return head,start,false end function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) - local snext=start.next + local snext=getnext(start) if not snext then return head,start,false else local prev,done=start,false local factor=tfmdata.parameters.factor local lookuptype=lookuptypes[lookupname] - while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do - local nextchar=snext.char + while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do + local nextchar=getchar(snext) local krn=kerns[nextchar] if not krn and marks[nextchar] then prev=snext - snext=snext.next + snext=getnext(snext) else if not krn then elseif type(krn)=="table" then if lookuptype=="pair" then local a,b=krn[2],krn[3] if a and #a>0 then - local startchar=start.char + local startchar=getchar(start) local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) if trace_kerns then logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) end end if b and #b>0 then - local startchar=start.char + local startchar=getchar(start) local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) if trace_kerns then logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) @@ -10509,7 +10444,7 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) elseif krn~=0 then local k=setkern(snext,factor,rlmode,krn) if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar)) + logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar)) end done=true end @@ -10544,13 +10479,13 @@ function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,looku return head,start,false end function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements) - local char=start.char + local char=getchar(start) local replacement=replacements[char] if replacement then if trace_singles then logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement)) end - start.char=replacement + setfield(start,"char",replacement) return head,start,true else return head,start,false @@ -10563,8 +10498,8 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," ")) end while current do - if current.id==glyph_code then - local currentchar=current.char + if getid(current)==glyph_code then + local currentchar=getchar(current) local lookupname=subtables[1] local replacement=lookuphash[lookupname] if not replacement then @@ -10581,21 +10516,21 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo if trace_singles then logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement)) end - current.char=replacement + setfield(current,"char",replacement) end end return head,start,true elseif current==stop then break else - current=current.next + current=getnext(current) end end return head,start,false end chainmores.gsub_single=chainprocs.gsub_single function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local replacements=lookuphash[lookupname] @@ -10624,8 +10559,8 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext local subtables=currentlookup.subtables local value=featurevalue==true and tfmdata.shared.features[kind] or featurevalue while current do - if current.id==glyph_code then - local currentchar=current.char + if getid(current)==glyph_code then + local currentchar=getchar(current) local lookupname=subtables[1] local alternatives=lookuphash[lookupname] if not alternatives then @@ -10640,7 +10575,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext if trace_alternatives then logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment) end - start.char=choice + setfield(start,"char",choice) else if trace_alternatives then logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment) @@ -10654,14 +10589,14 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext elseif current==stop then break else - current=current.next + current=getnext(current) end end return head,start,false end chainmores.gsub_alternate=chainprocs.gsub_alternate function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local ligatures=lookuphash[lookupname] @@ -10676,20 +10611,20 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) end else - local s=start.next + local s=getnext(start) local discfound=false local last=stop local nofreplacements=0 local skipmark=currentlookup.flags[1] while s do - local id=s.id + local id=getid(s) if id==disc_code then - s=s.next + s=getnext(s) discfound=true else - local schar=s.char + local schar=getchar(s) if skipmark and marks[schar] then - s=s.next + s=getnext(s) else local lg=ligatures[schar] if lg then @@ -10697,7 +10632,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, if s==stop then break else - s=s.next + s=getnext(s) end else break @@ -10714,7 +10649,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, if start==stop then logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2)) else - logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2)) + logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2)) end end head,start=toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound) @@ -10723,7 +10658,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, if start==stop then logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) else - logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char)) + logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop))) end end end @@ -10732,7 +10667,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext, end chainmores.gsub_ligature=chainprocs.gsub_ligature function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then local subtables=currentlookup.subtables local lookupname=subtables[1] @@ -10741,14 +10676,14 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext markanchors=markanchors[markchar] end if markanchors then - local base=start.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + local base=getprev(start) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) if marks[basechar] then while true do - base=base.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - basechar=base.char + base=getprev(base) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + basechar=getchar(base) if not marks[basechar] then break end @@ -10795,7 +10730,7 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext return head,start,false end function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then local subtables=currentlookup.subtables local lookupname=subtables[1] @@ -10804,14 +10739,14 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon markanchors=markanchors[markchar] end if markanchors then - local base=start.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + local base=getprev(start) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) if marks[basechar] then while true do - base=base.prev - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - basechar=base.char + base=getprev(base) + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + basechar=getchar(base) if not marks[basechar] then break end @@ -10823,7 +10758,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon end end end - local index=start[a_ligacomp] + local index=getattr(start,a_ligacomp) local baseanchors=descriptions[basechar].anchors if baseanchors then local baseanchors=baseanchors['baselig'] @@ -10862,7 +10797,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon return head,start,false end function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar=start.char + local markchar=getchar(start) if marks[markchar] then local subtables=currentlookup.subtables local lookupname=subtables[1] @@ -10871,20 +10806,20 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext markanchors=markanchors[markchar] end if markanchors then - local base=start.prev - local slc=start[a_ligacomp] + local base=getprev(start) + local slc=getattr(start,a_ligacomp) if slc then while base do - local blc=base[a_ligacomp] + local blc=getattr(base,a_ligacomp) if blc and blc~=slc then - base=base.prev + base=getprev(base) else break end end end - if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then - local basechar=base.char + if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then + local basechar=getchar(base) local baseanchors=descriptions[basechar].anchors if baseanchors then baseanchors=baseanchors['basemark'] @@ -10920,9 +10855,9 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext return head,start,false end function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local alreadydone=cursonce and start[a_cursbase] + local alreadydone=cursonce and getattr(start,a_cursbase) if not alreadydone then - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local exitanchors=lookuphash[lookupname] @@ -10936,11 +10871,11 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar)) end else - local nxt=start.next - while not done and nxt and nxt.id==glyph_code and nxt.font==currentfont and nxt.subtype<256 do - local nextchar=nxt.char + local nxt=getnext(start) + while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do + local nextchar=getchar(nxt) if marks[nextchar] then - nxt=nxt.next + nxt=getnext(nxt) else local entryanchors=descriptions[nextchar] if entryanchors then @@ -10974,7 +10909,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l return head,start,done else if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) + logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone) end return head,start,false end @@ -10982,7 +10917,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l return head,start,false end function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local kerns=lookuphash[lookupname] @@ -10999,9 +10934,9 @@ function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lo end chainmores.gpos_single=chainprocs.gpos_single function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) - local snext=start.next + local snext=getnext(start) if snext then - local startchar=start.char + local startchar=getchar(start) local subtables=currentlookup.subtables local lookupname=subtables[1] local kerns=lookuphash[lookupname] @@ -11011,26 +10946,26 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look local lookuptype=lookuptypes[lookupname] local prev,done=start,false local factor=tfmdata.parameters.factor - while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do - local nextchar=snext.char + while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do + local nextchar=getchar(snext) local krn=kerns[nextchar] if not krn and marks[nextchar] then prev=snext - snext=snext.next + snext=getnext(snext) else if not krn then elseif type(krn)=="table" then if lookuptype=="pair" then local a,b=krn[2],krn[3] if a and #a>0 then - local startchar=start.char + local startchar=getchar(start) local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) if trace_kerns then logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) end end if b and #b>0 then - local startchar=start.char + local startchar=getchar(start) local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) if trace_kerns then logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) @@ -11042,7 +10977,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look if a and a~=0 then local k=setkern(snext,factor,rlmode,a) if trace_kerns then - logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) + logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar)) end end if b and b~=0 then @@ -11053,7 +10988,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look elseif krn~=0 then local k=setkern(snext,factor,rlmode,krn) if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) + logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar)) end done=true end @@ -11074,6 +11009,10 @@ local function show_skip(kind,chainname,char,ck,class) logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2]) end end +local quit_on_no_replacement=true +directives.register("otf.chain.quitonnoreplacement",function(value) + quit_on_no_replacement=value +end) local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash) local flags=sequence.flags local done=false @@ -11091,7 +11030,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq local seq=ck[3] local s=#seq if s==1 then - match=current.id==glyph_code and current.font==currentfont and current.subtype<256 and seq[1][current.char] + match=getid(current)==glyph_code and getfont(current)==currentfont and getsubtype(current)<256 and seq[1][getchar(current)] else local f,l=ck[4],ck[5] if f==1 and f==l then @@ -11099,13 +11038,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if f==l then else local n=f+1 - last=last.next + last=getnext(last) while n<=l do if last then - local id=last.id + local id=getid(last) if id==glyph_code then - if last.font==currentfont and last.subtype<256 then - local char=last.char + if getfont(last)==currentfont and getsubtype(last)<256 then + local char=getchar(last) local ccd=descriptions[char] if ccd then local class=ccd.class @@ -11114,10 +11053,10 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if trace_skips then show_skip(kind,chainname,char,ck,class) end - last=last.next + last=getnext(last) elseif seq[n][char] then if n<l then - last=last.next + last=getnext(last) end n=n+1 else @@ -11133,7 +11072,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq break end elseif id==disc_code then - last=last.next + last=getnext(last) else match=false break @@ -11146,15 +11085,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq end end if match and f>1 then - local prev=start.prev + local prev=getprev(start) if prev then local n=f-1 while n>=1 do if prev then - local id=prev.id + local id=getid(prev) if id==glyph_code then - if prev.font==currentfont and prev.subtype<256 then - local char=prev.char + if getfont(prev)==currentfont and getsubtype(prev)<256 then + local char=getchar(prev) local ccd=descriptions[char] if ccd then local class=ccd.class @@ -11184,7 +11123,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq match=false break end - prev=prev.prev + prev=getprev(prev) elseif seq[n][32] then n=n -1 else @@ -11204,15 +11143,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq end end if match and s>l then - local current=last and last.next + local current=last and getnext(last) if current then local n=l+1 while n<=s do if current then - local id=current.id + local id=getid(current) if id==glyph_code then - if current.font==currentfont and current.subtype<256 then - local char=current.char + if getfont(current)==currentfont and getsubtype(current)<256 then + local char=getchar(current) local ccd=descriptions[char] if ccd then local class=ccd.class @@ -11242,7 +11181,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq match=false break end - current=current.next + current=getnext(current) elseif seq[n][32] then n=n+1 else @@ -11265,7 +11204,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if match then if trace_contexts then local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5] - local char=start.char + local char=getchar(start) if ck[9] then logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a", cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10]) @@ -11299,12 +11238,12 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq repeat if skipped then while true do - local char=start.char + local char=getchar(start) local ccd=descriptions[char] if ccd then local class=ccd.class if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then - start=start.next + start=getnext(start) else break end @@ -11334,7 +11273,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq end end if start then - start=start.next + start=getnext(start) else end until i>nofchainlookups @@ -11344,7 +11283,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq if replacements then head,start,done=chainprocs.reversesub(head,start,last,kind,chainname,ck,lookuphash,replacements) else - done=true + done=quit_on_no_replacement if trace_contexts then logprocess("%s: skipping match",cref(kind,chainname)) end @@ -11461,6 +11400,7 @@ local function featuresprocessor(head,font,attr) if not lookuphash then return head,false end + head=tonut(head) if trace_steps then checkstep(head) end @@ -11493,10 +11433,10 @@ local function featuresprocessor(head,font,attr) local handler=handlers[typ] local start=find_node_tail(head) while start do - local id=start.id + local id=getid(start) if id==glyph_code then - if start.font==font and start.subtype<256 then - local a=start[0] + if getfont(start)==font and getsubtype(start)<256 then + local a=getattr(start,0) if a then a=a==attr else @@ -11507,7 +11447,7 @@ local function featuresprocessor(head,font,attr) local lookupname=subtables[i] local lookupcache=lookuphash[lookupname] if lookupcache then - local lookupmatch=lookupcache[start.char] + local lookupmatch=lookupcache[getchar(start)] if lookupmatch then head,start,success=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if success then @@ -11518,15 +11458,15 @@ local function featuresprocessor(head,font,attr) report_missing_cache(typ,lookupname) end end - if start then start=start.prev end + if start then start=getprev(start) end else - start=start.prev + start=getprev(start) end else - start=start.prev + start=getprev(start) end else - start=start.prev + start=getprev(start) end end else @@ -11544,16 +11484,16 @@ local function featuresprocessor(head,font,attr) local head=start local done=false while start do - local id=start.id - if id==glyph_code and start.font==font and start.subtype<256 then - local a=start[0] + local id=getid(start) + if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then + local a=getattr(start,0) if a then - a=(a==attr) and (not attribute or start[a_state]==attribute) + a=(a==attr) and (not attribute or getattr(start,a_state)==attribute) else - a=not attribute or start[a_state]==attribute + a=not attribute or getattr(start,a_state)==attribute end if a then - local lookupmatch=lookupcache[start.char] + local lookupmatch=lookupcache[getchar(start)] if lookupmatch then local ok head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) @@ -11561,12 +11501,12 @@ local function featuresprocessor(head,font,attr) done=true end end - if start then start=start.next end + if start then start=getnext(start) end else - start=start.next + start=getnext(start) end else - start=start.next + start=getnext(start) end end if done then @@ -11575,18 +11515,18 @@ local function featuresprocessor(head,font,attr) end end local function kerndisc(disc) - local prev=disc.prev - local next=disc.next + local prev=getprev(disc) + local next=getnext(disc) if prev and next then - prev.next=next - local a=prev[0] + setfield(prev,"next",next) + local a=getattr(prev,0) if a then - a=(a==attr) and (not attribute or prev[a_state]==attribute) + a=(a==attr) and (not attribute or getattr(prev,a_state)==attribute) else - a=not attribute or prev[a_state]==attribute + a=not attribute or getattr(prev,a_state)==attribute end if a then - local lookupmatch=lookupcache[prev.char] + local lookupmatch=lookupcache[getchar(prev)] if lookupmatch then local h,d,ok=handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) if ok then @@ -11595,22 +11535,22 @@ local function featuresprocessor(head,font,attr) end end end - prev.next=disc + setfield(prev,"next",disc) end return next end while start do - local id=start.id + local id=getid(start) if id==glyph_code then - if start.font==font and start.subtype<256 then - local a=start[0] + if getfont(start)==font and getsubtype(start)<256 then + local a=getattr(start,0) if a then - a=(a==attr) and (not attribute or start[a_state]==attribute) + a=(a==attr) and (not attribute or getattr(start,a_state)==attribute) else - a=not attribute or start[a_state]==attribute + a=not attribute or getattr(start,a_state)==attribute end if a then - local lookupmatch=lookupcache[start.char] + local lookupmatch=lookupcache[getchar(start)] if lookupmatch then local ok head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) @@ -11618,38 +11558,38 @@ local function featuresprocessor(head,font,attr) success=true end end - if start then start=start.next end + if start then start=getnext(start) end else - start=start.next + start=getnext(start) end else - start=start.next + start=getnext(start) end elseif id==disc_code then - if start.subtype==discretionary_code then - local pre=start.pre + if getsubtype(start)==discretionary_code then + local pre=getfield(start,"pre") if pre then local new=subrun(pre) - if new then start.pre=new end + if new then setfield(start,"pre",new) end end - local post=start.post + local post=getfield(start,"post") if post then local new=subrun(post) - if new then start.post=new end + if new then setfield(start,"post",new) end end - local replace=start.replace + local replace=getfield(start,"replace") if replace then local new=subrun(replace) - if new then start.replace=new end + if new then setfield(start,"replace",new) end end elseif typ=="gpos_single" or typ=="gpos_pair" then kerndisc(start) end - start=start.next + start=getnext(start) elseif id==whatsit_code then - local subtype=start.subtype + local subtype=getsubtype(start) if subtype==dir_code then - local dir=start.dir + local dir=getfield(start,"dir") if dir=="+TRT" or dir=="+TLT" then topstack=topstack+1 dirstack[topstack]=dir @@ -11668,7 +11608,7 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir) end elseif subtype==localpar_code then - local dir=start.dir + local dir=getfield(start,"dir") if dir=="TRT" then rlparmode=-1 elseif dir=="TLT" then @@ -11681,11 +11621,11 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode) end end - start=start.next + start=getnext(start) elseif id==math_code then - start=end_of_math(start).next + start=getnext(end_of_math(start)) else - start=start.next + start=getnext(start) end end end @@ -11694,20 +11634,20 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then local head=start local done=false while start do - local id=start.id - if id==glyph_code and start.id==font and start.subtype<256 then - local a=start[0] + local id=getid(start) + if id==glyph_code and getfont(start)==font and getsubtype(start)<256 then + local a=getattr(start,0) if a then - a=(a==attr) and (not attribute or start[a_state]==attribute) + a=(a==attr) and (not attribute or getattr(start,a_state)==attribute) else - a=not attribute or start[a_state]==attribute + a=not attribute or getattr(start,a_state)==attribute end if a then for i=1,ns do local lookupname=subtables[i] local lookupcache=lookuphash[lookupname] if lookupcache then - local lookupmatch=lookupcache[start.char] + local lookupmatch=lookupcache[getchar(start)] if lookupmatch then local ok head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) @@ -11722,12 +11662,12 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then report_missing_cache(typ,lookupname) end end - if start then start=start.next end + if start then start=getnext(start) end else - start=start.next + start=getnext(start) end else - start=start.next + start=getnext(start) end end if done then @@ -11736,22 +11676,22 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then end end local function kerndisc(disc) - local prev=disc.prev - local next=disc.next + local prev=getprev(disc) + local next=getnext(disc) if prev and next then - prev.next=next - local a=prev[0] + setfield(prev,"next",next) + local a=getattr(prev,0) if a then - a=(a==attr) and (not attribute or prev[a_state]==attribute) + a=(a==attr) and (not attribute or getattr(prev,a_state)==attribute) else - a=not attribute or prev[a_state]==attribute + a=not attribute or getattr(prev,a_state)==attribute end if a then for i=1,ns do local lookupname=subtables[i] local lookupcache=lookuphash[lookupname] if lookupcache then - local lookupmatch=lookupcache[prev.char] + local lookupmatch=lookupcache[getchar(prev)] if lookupmatch then local h,d,ok=handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) if ok then @@ -11764,26 +11704,26 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then end end end - prev.next=disc + setfield(prev,"next",disc) end return next end while start do - local id=start.id + local id=getid(start) if id==glyph_code then - if start.font==font and start.subtype<256 then - local a=start[0] + if getfont(start)==font and getsubtype(start)<256 then + local a=getattr(start,0) if a then - a=(a==attr) and (not attribute or start[a_state]==attribute) + a=(a==attr) and (not attribute or getattr(start,a_state)==attribute) else - a=not attribute or start[a_state]==attribute + a=not attribute or getattr(start,a_state)==attribute end if a then for i=1,ns do local lookupname=subtables[i] local lookupcache=lookuphash[lookupname] if lookupcache then - local lookupmatch=lookupcache[start.char] + local lookupmatch=lookupcache[getchar(start)] if lookupmatch then local ok head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) @@ -11798,38 +11738,38 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then report_missing_cache(typ,lookupname) end end - if start then start=start.next end + if start then start=getnext(start) end else - start=start.next + start=getnext(start) end else - start=start.next + start=getnext(start) end elseif id==disc_code then - if start.subtype==discretionary_code then - local pre=start.pre + if getsubtype(start)==discretionary_code then + local pre=getfield(start,"pre") if pre then local new=subrun(pre) - if new then start.pre=new end + if new then setfield(start,"pre",new) end end - local post=start.post + local post=getfield(start,"post") if post then local new=subrun(post) - if new then start.post=new end + if new then setfield(start,"post",new) end end - local replace=start.replace + local replace=getfield(start,"replace") if replace then local new=subrun(replace) - if new then start.replace=new end + if new then setfield(start,"replace",new) end end elseif typ=="gpos_single" or typ=="gpos_pair" then kerndisc(start) end - start=start.next + start=getnext(start) elseif id==whatsit_code then - local subtype=start.subtype + local subtype=getsubtype(start) if subtype==dir_code then - local dir=start.dir + local dir=getfield(start,"dir") if dir=="+TRT" or dir=="+TLT" then topstack=topstack+1 dirstack[topstack]=dir @@ -11848,7 +11788,7 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir) end elseif subtype==localpar_code then - local dir=start.dir + local dir=getfield(start,"dir") if dir=="TRT" then rlparmode=-1 elseif dir=="TLT" then @@ -11861,11 +11801,11 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode) end end - start=start.next + start=getnext(start) elseif id==math_code then - start=end_of_math(start).next + start=getnext(end_of_math(start)) else - start=start.next + start=getnext(start) end end end @@ -11877,6 +11817,7 @@ elseif typ=="gpos_single" or typ=="gpos_pair" then registerstep(head) end end + head=tonode(head) return head,done end local function generic(lookupdata,lookupname,unicode,lookuphash) diff --git a/tex/generic/context/luatex/luatex-fonts-otn.lua b/tex/generic/context/luatex/luatex-fonts-otn.lua deleted file mode 100644 index c57be5f02..000000000 --- a/tex/generic/context/luatex/luatex-fonts-otn.lua +++ /dev/null @@ -1,2848 +0,0 @@ -if not modules then modules = { } end modules ['font-otn'] = { - version = 1.001, - comment = "companion to font-ini.mkiv", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", -} - --- preprocessors = { "nodes" } - --- this is still somewhat preliminary and it will get better in due time; --- much functionality could only be implemented thanks to the husayni font --- of Idris Samawi Hamid to who we dedicate this module. - --- in retrospect it always looks easy but believe it or not, it took a lot --- of work to get proper open type support done: buggy fonts, fuzzy specs, --- special made testfonts, many skype sessions between taco, idris and me, --- torture tests etc etc ... unfortunately the code does not show how much --- time it took ... - --- todo: --- --- kerning is probably not yet ok for latin around dics nodes (interesting challenge) --- extension infrastructure (for usage out of context) --- sorting features according to vendors/renderers --- alternative loop quitters --- check cursive and r2l --- find out where ignore-mark-classes went --- default features (per language, script) --- handle positions (we need example fonts) --- handle gpos_single (we might want an extra width field in glyph nodes because adding kerns might interfere) --- mark (to mark) code is still not what it should be (too messy but we need some more extreem husayni tests) --- remove some optimizations (when I have a faster machine) --- --- maybe redo the lot some way (more context specific) - ---[[ldx-- -<p>This module is a bit more split up that I'd like but since we also want to test -with plain <l n='tex'/> it has to be so. This module is part of <l n='context'/> -and discussion about improvements and functionality mostly happens on the -<l n='context'/> mailing list.</p> - -<p>The specification of OpenType is kind of vague. Apart from a lack of a proper -free specifications there's also the problem that Microsoft and Adobe -may have their own interpretation of how and in what order to apply features. -In general the Microsoft website has more detailed specifications and is a -better reference. There is also some information in the FontForge help files.</p> - -<p>Because there is so much possible, fonts might contain bugs and/or be made to -work with certain rederers. These may evolve over time which may have the side -effect that suddenly fonts behave differently.</p> - -<p>After a lot of experiments (mostly by Taco, me and Idris) we're now at yet another -implementation. Of course all errors are mine and of course the code can be -improved. There are quite some optimizations going on here and processing speed -is currently acceptable. Not all functions are implemented yet, often because I -lack the fonts for testing. Many scripts are not yet supported either, but I will -look into them as soon as <l n='context'/> users ask for it.</p> - -<p>Because there are different interpretations possible, I will extend the code -with more (configureable) variants. I can also add hooks for users so that they can -write their own extensions.</p> - -<p>Glyphs are indexed not by unicode but in their own way. This is because there is no -relationship with unicode at all, apart from the fact that a font might cover certain -ranges of characters. One character can have multiple shapes. However, at the -<l n='tex'/> end we use unicode so and all extra glyphs are mapped into a private -space. This is needed because we need to access them and <l n='tex'/> has to include -then in the output eventually.</p> - -<p>The raw table as it coms from <l n='fontforge'/> gets reorganized in to fit out needs. -In <l n='context'/> that table is packed (similar tables are shared) and cached on disk -so that successive runs can use the optimized table (after loading the table is -unpacked). The flattening code used later is a prelude to an even more compact table -format (and as such it keeps evolving).</p> - -<p>This module is sparsely documented because it is a moving target. The table format -of the reader changes and we experiment a lot with different methods for supporting -features.</p> - -<p>As with the <l n='afm'/> code, we may decide to store more information in the -<l n='otf'/> table.</p> - -<p>Incrementing the version number will force a re-cache. We jump the number by one -when there's a fix in the <l n='fontforge'/> library or <l n='lua'/> code that -results in different tables.</p> ---ldx]]-- - --- action handler chainproc chainmore comment --- --- gsub_single ok ok ok --- gsub_multiple ok ok not implemented yet --- gsub_alternate ok ok not implemented yet --- gsub_ligature ok ok ok --- gsub_context ok -- --- gsub_contextchain ok -- --- gsub_reversecontextchain ok -- --- chainsub -- ok --- reversesub -- ok --- gpos_mark2base ok ok --- gpos_mark2ligature ok ok --- gpos_mark2mark ok ok --- gpos_cursive ok untested --- gpos_single ok ok --- gpos_pair ok ok --- gpos_context ok -- --- gpos_contextchain ok -- --- --- todo: contextpos and contextsub and class stuff --- --- actions: --- --- handler : actions triggered by lookup --- chainproc : actions triggered by contextual lookup --- chainmore : multiple substitutions triggered by contextual lookup (e.g. fij -> f + ij) --- --- remark: the 'not implemented yet' variants will be done when we have fonts that use them --- remark: we need to check what to do with discretionaries - --- We used to have independent hashes for lookups but as the tags are unique --- we now use only one hash. If needed we can have multiple again but in that --- case I will probably prefix (i.e. rename) the lookups in the cached font file. - --- Todo: make plugin feature that operates on char/glyphnode arrays - -local concat, insert, remove = table.concat, table.insert, table.remove -local gmatch, gsub, find, match, lower, strip = string.gmatch, string.gsub, string.find, string.match, string.lower, string.strip -local type, next, tonumber, tostring = type, next, tonumber, tostring -local lpegmatch = lpeg.match -local random = math.random -local formatters = string.formatters - -local logs, trackers, nodes, attributes = logs, trackers, nodes, attributes - -local registertracker = trackers.register - -local fonts = fonts -local otf = fonts.handlers.otf - -local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end) -local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end) -local trace_multiples = false registertracker("otf.multiples", function(v) trace_multiples = v end) -local trace_alternatives = false registertracker("otf.alternatives", function(v) trace_alternatives = v end) -local trace_ligatures = false registertracker("otf.ligatures", function(v) trace_ligatures = v end) -local trace_contexts = false registertracker("otf.contexts", function(v) trace_contexts = v end) -local trace_marks = false registertracker("otf.marks", function(v) trace_marks = v end) -local trace_kerns = false registertracker("otf.kerns", function(v) trace_kerns = v end) -local trace_cursive = false registertracker("otf.cursive", function(v) trace_cursive = v end) -local trace_preparing = false registertracker("otf.preparing", function(v) trace_preparing = v end) -local trace_bugs = false registertracker("otf.bugs", function(v) trace_bugs = v end) -local trace_details = false registertracker("otf.details", function(v) trace_details = v end) -local trace_applied = false registertracker("otf.applied", function(v) trace_applied = v end) -local trace_steps = false registertracker("otf.steps", function(v) trace_steps = v end) -local trace_skips = false registertracker("otf.skips", function(v) trace_skips = v end) -local trace_directions = false registertracker("otf.directions", function(v) trace_directions = v end) - -local report_direct = logs.reporter("fonts","otf direct") -local report_subchain = logs.reporter("fonts","otf subchain") -local report_chain = logs.reporter("fonts","otf chain") -local report_process = logs.reporter("fonts","otf process") -local report_prepare = logs.reporter("fonts","otf prepare") -local report_warning = logs.reporter("fonts","otf warning") - -registertracker("otf.verbose_chain", function(v) otf.setcontextchain(v and "verbose") end) -registertracker("otf.normal_chain", function(v) otf.setcontextchain(v and "normal") end) - -registertracker("otf.replacements", "otf.singles,otf.multiples,otf.alternatives,otf.ligatures") -registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive") -registertracker("otf.actions","otf.replacements,otf.positions") -registertracker("otf.injections","nodes.injections") - -registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing") - -local insert_node_after = node.insert_after -local delete_node = nodes.delete -local copy_node = node.copy -local find_node_tail = node.tail or node.slide -local flush_node_list = node.flush_list -local end_of_math = node.end_of_math - -local setmetatableindex = table.setmetatableindex - -local zwnj = 0x200C -local zwj = 0x200D -local wildcard = "*" -local default = "dflt" - -local nodecodes = nodes.nodecodes -local whatcodes = nodes.whatcodes -local glyphcodes = nodes.glyphcodes -local disccodes = nodes.disccodes - -local glyph_code = nodecodes.glyph -local glue_code = nodecodes.glue -local disc_code = nodecodes.disc -local whatsit_code = nodecodes.whatsit -local math_code = nodecodes.math - -local dir_code = whatcodes.dir -local localpar_code = whatcodes.localpar - -local discretionary_code = disccodes.discretionary - -local ligature_code = glyphcodes.ligature - -local privateattribute = attributes.private - --- Something is messed up: we have two mark / ligature indices, one at the injection --- end and one here ... this is bases in KE's patches but there is something fishy --- there as I'm pretty sure that for husayni we need some connection (as it's much --- more complex than an average font) but I need proper examples of all cases, not --- of only some. - -local a_state = privateattribute('state') -local a_markbase = privateattribute('markbase') -local a_markmark = privateattribute('markmark') -local a_markdone = privateattribute('markdone') -- assigned at the injection end -local a_cursbase = privateattribute('cursbase') -local a_curscurs = privateattribute('curscurs') -local a_cursdone = privateattribute('cursdone') -local a_kernpair = privateattribute('kernpair') -local a_ligacomp = privateattribute('ligacomp') -- assigned here (ideally it should be combined) - -local injections = nodes.injections -local setmark = injections.setmark -local setcursive = injections.setcursive -local setkern = injections.setkern -local setpair = injections.setpair - -local markonce = true -local cursonce = true -local kernonce = true - -local fonthashes = fonts.hashes -local fontdata = fonthashes.identifiers - -local otffeatures = fonts.constructors.newfeatures("otf") -local registerotffeature = otffeatures.register - -local onetimemessage = fonts.loggers.onetimemessage or function() end - -otf.defaultnodealternate = "none" -- first last - --- we share some vars here, after all, we have no nested lookups and less code - -local tfmdata = false -local characters = false -local descriptions = false -local resources = false -local marks = false -local currentfont = false -local lookuptable = false -local anchorlookups = false -local lookuptypes = false -local handlers = { } -local rlmode = 0 -local featurevalue = false - --- head is always a whatsit so we can safely assume that head is not changed - --- we use this for special testing and documentation - -local checkstep = (nodes and nodes.tracers and nodes.tracers.steppers.check) or function() end -local registerstep = (nodes and nodes.tracers and nodes.tracers.steppers.register) or function() end -local registermessage = (nodes and nodes.tracers and nodes.tracers.steppers.message) or function() end - -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_direct(...) -end - -local function logwarning(...) - report_direct(...) -end - -local f_unicode = formatters["%U"] -local f_uniname = formatters["%U (%s)"] -local f_unilist = formatters["% t (% t)"] - -local function gref(n) -- currently the same as in font-otb - if type(n) == "number" then - local description = descriptions[n] - local name = description and description.name - if name then - return f_uniname(n,name) - else - return f_unicode(n) - end - elseif n then - local num, nam = { }, { } - for i=1,#n do - local ni = n[i] - if tonumber(ni) then -- later we will start at 2 - local di = descriptions[ni] - num[i] = f_unicode(ni) - nam[i] = di and di.name or "-" - end - end - return f_unilist(num,nam) - else - return "<error in node mode tracing>" - end -end - -local function cref(kind,chainname,chainlookupname,lookupname,index) -- not in the mood to alias f_ - if index then - return formatters["feature %a, chain %a, sub %a, lookup %a, index %a"](kind,chainname,chainlookupname,lookupname,index) - elseif lookupname then - return formatters["feature %a, chain %a, sub %a, lookup %a"](kind,chainname,chainlookupname,lookupname) - elseif chainlookupname then - return formatters["feature %a, chain %a, sub %a"](kind,chainname,chainlookupname) - elseif chainname then - return formatters["feature %a, chain %a"](kind,chainname) - else - return formatters["feature %a"](kind) - end -end - -local function pref(kind,lookupname) - return formatters["feature %a, lookup %a"](kind,lookupname) -end - --- We can assume that languages that use marks are not hyphenated. We can also assume --- that at most one discretionary is present. - --- We do need components in funny kerning mode but maybe I can better reconstruct then --- as we do have the font components info available; removing components makes the --- previous code much simpler. Also, later on copying and freeing becomes easier. --- However, for arabic we need to keep them around for the sake of mark placement --- and indices. - -local function copy_glyph(g) -- next and prev are untouched ! - local components = g.components - if components then - g.components = nil - local n = copy_node(g) - g.components = components - return n - else - return copy_node(g) - end -end - --- start is a mark and we need to keep that one - -local function markstoligature(kind,lookupname,head,start,stop,char) - if start == stop and start.char == char then - return head, start - else - local prev = start.prev - local next = stop.next - start.prev = nil - stop.next = nil - local base = copy_glyph(start) - if head == start then - head = base - end - base.char = char - base.subtype = ligature_code - base.components = start - if prev then - prev.next = base - end - if next then - next.prev = base - end - base.next = next - base.prev = prev - return head, base - end -end - --- The next code is somewhat complicated by the fact that some fonts can have ligatures made --- from ligatures that themselves have marks. This was identified by Kai in for instance --- arabtype: KAF LAM SHADDA ALEF FATHA (0x0643 0x0644 0x0651 0x0627 0x064E). This becomes --- KAF LAM-ALEF with a SHADDA on the first and a FATHA op de second component. In a next --- iteration this becomes a KAF-LAM-ALEF with a SHADDA on the second and a FATHA on the --- third component. - -local function getcomponentindex(start) - if start.id ~= glyph_code then - return 0 - elseif start.subtype == ligature_code then - local i = 0 - local components = start.components - while components do - i = i + getcomponentindex(components) - components = components.next - end - return i - elseif not marks[start.char] then - return 1 - else - return 0 - end -end - --- eventually we will do positioning in an other way (needs addional w/h/d fields) - -local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) -- brr head - if start == stop and start.char == char then - start.char = char - return head, start - end - local prev = start.prev - local next = stop.next - start.prev = nil - stop.next = nil - local base = copy_glyph(start) - if start == head then - head = base - end - base.char = char - base.subtype = ligature_code - base.components = start -- start can have components - if prev then - prev.next = base - end - if next then - next.prev = base - end - base.next = next - base.prev = prev - if not discfound then - local deletemarks = markflag ~= "mark" - local components = start - local baseindex = 0 - local componentindex = 0 - local head = base - local current = base - -- first we loop over the glyphs in start .. stop - while start do - local char = start.char - if not marks[char] then - baseindex = baseindex + componentindex - componentindex = getcomponentindex(start) - elseif not deletemarks then -- quite fishy - start[a_ligacomp] = baseindex + (start[a_ligacomp] or componentindex) - if trace_marks then - logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) - end - head, current = insert_node_after(head,current,copy_node(start)) -- unlikely that mark has components - elseif trace_marks then - logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char)) - end - start = start.next - end - -- we can have one accent as part of a lookup and another following - -- local start = components -- was wrong (component scanning was introduced when more complex ligs in devanagari was added) - local start = current.next - while start and start.id == glyph_code do - local char = start.char - if marks[char] then - start[a_ligacomp] = baseindex + (start[a_ligacomp] or componentindex) - if trace_marks then - logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp]) - end - else - break - end - start = start.next - end - end - return head, base -end - -function handlers.gsub_single(head,start,kind,lookupname,replacement) - if trace_singles then - logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement)) - end - start.char = replacement - return head, start, true -end - -local function get_alternative_glyph(start,alternatives,value,trace_alternatives) - local n = #alternatives - if value == "random" then - local r = random(1,n) - return alternatives[r], trace_alternatives and formatters["value %a, taking %a"](value,r) - elseif value == "first" then - return alternatives[1], trace_alternatives and formatters["value %a, taking %a"](value,1) - elseif value == "last" then - return alternatives[n], trace_alternatives and formatters["value %a, taking %a"](value,n) - else - value = tonumber(value) - if type(value) ~= "number" then - return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,1) - elseif value > n then - local defaultalt = otf.defaultnodealternate - if defaultalt == "first" then - return alternatives[n], trace_alternatives and formatters["invalid value %s, taking %a"](value,1) - elseif defaultalt == "last" then - return alternatives[1], trace_alternatives and formatters["invalid value %s, taking %a"](value,n) - else - return false, trace_alternatives and formatters["invalid value %a, %s"](value,"out of range") - end - elseif value == 0 then - return start.char, trace_alternatives and formatters["invalid value %a, %s"](value,"no change") - elseif value < 1 then - return alternatives[1], trace_alternatives and formatters["invalid value %a, taking %a"](value,1) - else - return alternatives[value], trace_alternatives and formatters["value %a, taking %a"](value,value) - end - end -end - -local function multiple_glyphs(head,start,multiple,ignoremarks) - local nofmultiples = #multiple - if nofmultiples > 0 then - start.char = multiple[1] - if nofmultiples > 1 then - local sn = start.next - for k=2,nofmultiples do -- todo: use insert_node --- untested: --- --- while ignoremarks and marks[sn.char] then --- local sn = sn.next --- end - local n = copy_node(start) -- ignore components - n.char = multiple[k] - n.next = sn - n.prev = start - if sn then - sn.prev = n - end - start.next = n - start = n - end - end - return head, start, true - else - if trace_multiples then - logprocess("no multiple for %s",gref(start.char)) - end - return head, start, false - end -end - -function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence) - local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue - local choice, comment = get_alternative_glyph(start,alternative,value,trace_alternatives) - if choice then - if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(start.char),choice,gref(choice),comment) - end - start.char = choice - else - if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(start.char),comment) - end - end - return head, start, true -end - -function handlers.gsub_multiple(head,start,kind,lookupname,multiple,sequence) - if trace_multiples then - logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple)) - end - return multiple_glyphs(head,start,multiple,sequence.flags[1]) -end - -function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence) - local s, stop, discfound = start.next, nil, false - local startchar = start.char - if marks[startchar] then - while s do - local id = s.id - if id == glyph_code and s.font == currentfont and s.subtype<256 then - local lg = ligature[s.char] - if lg then - stop = s - ligature = lg - s = s.next - else - break - end - else - break - end - end - if stop then - local lig = ligature.ligature - if lig then - if trace_ligatures then - local stopchar = stop.char - head, start = markstoligature(kind,lookupname,head,start,stop,lig) - logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) - else - head, start = markstoligature(kind,lookupname,head,start,stop,lig) - end - return head, start, true - else - -- ok, goto next lookup - end - end - else - local skipmark = sequence.flags[1] - while s do - local id = s.id - if id == glyph_code and s.subtype<256 then - if s.font == currentfont then - local char = s.char - if skipmark and marks[char] then - s = s.next - else - local lg = ligature[char] - if lg then - stop = s - ligature = lg - s = s.next - else - break - end - end - else - break - end - elseif id == disc_code then - discfound = true - s = s.next - else - break - end - end - local lig = ligature.ligature - if lig then - if stop then - if trace_ligatures then - local stopchar = stop.char - head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound) - logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char)) - else - head, start = toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound) - end - return head, start, true - else - -- weird but happens (in some arabic font) - start.char = lig - if trace_ligatures then - logprocess("%s: replacing %s by (no real) ligature %s case 3",pref(kind,lookupname),gref(startchar),gref(lig)) - end - return head, start, true - end - else - -- weird but happens - end - end - return head, start, false -end - ---[[ldx-- -<p>We get hits on a mark, but we're not sure if the it has to be applied so -we need to explicitly test for basechar, baselig and basemark entries.</p> ---ldx]]-- - -function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence) - local markchar = start.char - if marks[markchar] then - local base = start.prev -- [glyph] [start=mark] - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then - local basechar = base.char - if marks[basechar] then - while true do - base = base.prev - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then - basechar = base.char - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) - end - return head, start, false - end - end - end - local baseanchors = descriptions[basechar] - if baseanchors then - baseanchors = baseanchors.anchors - end - if baseanchors then - local baseanchors = baseanchors['basechar'] - if baseanchors then - local al = anchorlookups[lookupname] - for anchor,ba in next, baseanchors do - if al[anchor] then - local ma = markanchors[anchor] - if ma then - local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)", - pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head, start, true - end - end - end - if trace_bugs then - logwarning("%s, no matching anchors for mark %s and base %s",pref(kind,lookupname),gref(markchar),gref(basechar)) - end - end - elseif trace_bugs then - -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar)) - onetimemessage(currentfont,basechar,"no base anchors",report_fonts) - end - elseif trace_bugs then - logwarning("%s: prev node is no char",pref(kind,lookupname)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) - end - return head, start, false -end - -function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence) - -- check chainpos variant - local markchar = start.char - if marks[markchar] then - local base = start.prev -- [glyph] [optional marks] [start=mark] - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then - local basechar = base.char - if marks[basechar] then - while true do - base = base.prev - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then - basechar = base.char - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) - end - return head, start, false - end - end - end - local index = start[a_ligacomp] - local baseanchors = descriptions[basechar] - if baseanchors then - baseanchors = baseanchors.anchors - if baseanchors then - local baseanchors = baseanchors['baselig'] - if baseanchors then - local al = anchorlookups[lookupname] - for anchor, ba in next, baseanchors do - if al[anchor] then - local ma = markanchors[anchor] - if ma then - ba = ba[index] - if ba then - local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma) -- index - if trace_marks then - logprocess("%s, anchor %s, index %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)", - pref(kind,lookupname),anchor,index,bound,gref(markchar),gref(basechar),index,dx,dy) - end - return head, start, true - else - if trace_bugs then - logwarning("%s: no matching anchors for mark %s and baselig %s with index %a",pref(kind,lookupname),gref(markchar),gref(basechar),index) - end - end - end - end - end - if trace_bugs then - logwarning("%s: no matching anchors for mark %s and baselig %s",pref(kind,lookupname),gref(markchar),gref(basechar)) - end - end - end - elseif trace_bugs then - -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar)) - onetimemessage(currentfont,basechar,"no base anchors",report_fonts) - end - elseif trace_bugs then - logwarning("%s: prev node is no char",pref(kind,lookupname)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) - end - return head, start, false -end - -function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence) - local markchar = start.char - if marks[markchar] then - local base = start.prev -- [glyph] [basemark] [start=mark] - local slc = start[a_ligacomp] - if slc then -- a rather messy loop ... needs checking with husayni - while base do - local blc = base[a_ligacomp] - if blc and blc ~= slc then - base = base.prev - else - break - end - end - end - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then -- subtype test can go - local basechar = base.char - local baseanchors = descriptions[basechar] - if baseanchors then - baseanchors = baseanchors.anchors - if baseanchors then - baseanchors = baseanchors['basemark'] - if baseanchors then - local al = anchorlookups[lookupname] - for anchor,ba in next, baseanchors do - if al[anchor] then - local ma = markanchors[anchor] - if ma then - local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,true) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)", - pref(kind,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head, start, true - end - end - end - if trace_bugs then - logwarning("%s: no matching anchors for mark %s and basemark %s",pref(kind,lookupname),gref(markchar),gref(basechar)) - end - end - end - elseif trace_bugs then - -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(basechar)) - onetimemessage(currentfont,basechar,"no base anchors",report_fonts) - end - elseif trace_bugs then - logwarning("%s: prev node is no mark",pref(kind,lookupname)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",pref(kind,lookupname),gref(markchar)) - end - return head, start, false -end - -function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) -- to be checked - local alreadydone = cursonce and start[a_cursbase] - if not alreadydone then - local done = false - local startchar = start.char - if marks[startchar] then - if trace_cursive then - logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar)) - end - else - local nxt = start.next - while not done and nxt and nxt.id == glyph_code and nxt.font == currentfont and nxt.subtype<256 do - local nextchar = nxt.char - if marks[nextchar] then - -- should not happen (maybe warning) - nxt = nxt.next - else - local entryanchors = descriptions[nextchar] - if entryanchors then - entryanchors = entryanchors.anchors - if entryanchors then - entryanchors = entryanchors['centry'] - if entryanchors then - local al = anchorlookups[lookupname] - for anchor, entry in next, entryanchors do - if al[anchor] then - local exit = exitanchors[anchor] - if exit then - local dx, dy, bound = setcursive(start,nxt,tfmdata.parameters.factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) - if trace_cursive then - logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode) - end - done = true - break - end - end - end - end - end - elseif trace_bugs then - -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar)) - onetimemessage(currentfont,startchar,"no entry anchors",report_fonts) - end - break - end - end - end - return head, start, done - else - if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) - end - return head, start, false - end -end - -function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence) - local startchar = start.char - local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar]) - if trace_kerns then - logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h) - end - return head, start, false -end - -function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence) - -- todo: kerns in disc nodes: pre, post, replace -> loop over disc too - -- todo: kerns in components of ligatures - local snext = start.next - if not snext then - return head, start, false - else - local prev, done = start, false - local factor = tfmdata.parameters.factor - local lookuptype = lookuptypes[lookupname] - while snext and snext.id == glyph_code and snext.font == currentfont and snext.subtype<256 do - local nextchar = snext.char - local krn = kerns[nextchar] - if not krn and marks[nextchar] then - prev = snext - snext = snext.next - else - if not krn then - -- skip - elseif type(krn) == "table" then - if lookuptype == "pair" then -- probably not needed - local a, b = krn[2], krn[3] - if a and #a > 0 then - local startchar = start.char - local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) - if trace_kerns then - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) - end - end - if b and #b > 0 then - local startchar = start.char - local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) - if trace_kerns then - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h) - end - end - else -- wrong ... position has different entries - report_process("%s: check this out (old kern stuff)",pref(kind,lookupname)) - -- local a, b = krn[2], krn[6] - -- if a and a ~= 0 then - -- local k = setkern(snext,factor,rlmode,a) - -- if trace_kerns then - -- logprocess("%s: inserting first kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar)) - -- end - -- end - -- if b and b ~= 0 then - -- logwarning("%s: ignoring second kern xoff %s",pref(kind,lookupname),b*factor) - -- end - end - done = true - elseif krn ~= 0 then - local k = setkern(snext,factor,rlmode,krn) - if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar)) - end - done = true - end - break - end - end - return head, start, done - end -end - ---[[ldx-- -<p>I will implement multiple chain replacements once I run into a font that uses -it. It's not that complex to handle.</p> ---ldx]]-- - -local chainmores = { } -local chainprocs = { } - -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_subchain(...) -end - -local logwarning = report_subchain - -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_chain(...) -end - -local logwarning = report_chain - --- We could share functions but that would lead to extra function calls with many --- arguments, redundant tests and confusing messages. - -function chainprocs.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname) - logwarning("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname)) - return head, start, false -end - -function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,lookuphash,lookuplist,chainlookupname,n) - logprocess("%s: a direct call to chainsub cannot happen",cref(kind,chainname,chainlookupname)) - return head, start, false -end - --- The reversesub is a special case, which is why we need to store the replacements --- in a bit weird way. There is no lookup and the replacement comes from the lookup --- itself. It is meant mostly for dealing with Urdu. - -function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements) - local char = start.char - local replacement = replacements[char] - if replacement then - if trace_singles then - logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement)) - end - start.char = replacement - return head, start, true - else - return head, start, false - end -end - ---[[ldx-- -<p>This chain stuff is somewhat tricky since we can have a sequence of actions to be -applied: single, alternate, multiple or ligature where ligature can be an invalid -one in the sense that it will replace multiple by one but not neccessary one that -looks like the combination (i.e. it is the counterpart of multiple then). For -example, the following is valid:</p> - -<typing> -<line>xxxabcdexxx [single a->A][multiple b->BCD][ligature cde->E] xxxABCDExxx</line> -</typing> - -<p>Therefore we we don't really do the replacement here already unless we have the -single lookup case. The efficiency of the replacements can be improved by deleting -as less as needed but that would also make the code even more messy.</p> ---ldx]]-- - --- local function delete_till_stop(head,start,stop,ignoremarks) -- keeps start --- local n = 1 --- if start == stop then --- -- done --- elseif ignoremarks then --- repeat -- start x x m x x stop => start m --- local next = start.next --- if not marks[next.char] then --- local components = next.components --- if components then -- probably not needed --- flush_node_list(components) --- end --- head = delete_node(head,next) --- end --- n = n + 1 --- until next == stop --- else -- start x x x stop => start --- repeat --- local next = start.next --- local components = next.components --- if components then -- probably not needed --- flush_node_list(components) --- end --- head = delete_node(head,next) --- n = n + 1 --- until next == stop --- end --- return head, n --- end - ---[[ldx-- -<p>Here we replace start by a single variant, First we delete the rest of the -match.</p> ---ldx]]-- - -function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) - -- todo: marks ? - local current = start - local subtables = currentlookup.subtables - if #subtables > 1 then - logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," ")) - end - while current do - if current.id == glyph_code then - local currentchar = current.char - local lookupname = subtables[1] -- only 1 - local replacement = lookuphash[lookupname] - if not replacement then - if trace_bugs then - logwarning("%s: no single hits",cref(kind,chainname,chainlookupname,lookupname,chainindex)) - end - else - replacement = replacement[currentchar] - if not replacement or replacement == "" then - if trace_bugs then - logwarning("%s: no single for %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar)) - end - else - if trace_singles then - logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement)) - end - current.char = replacement - end - end - return head, start, true - elseif current == stop then - break - else - current = current.next - end - end - return head, start, false -end - -chainmores.gsub_single = chainprocs.gsub_single - ---[[ldx-- -<p>Here we replace start by a sequence of new glyphs. First we delete the rest of -the match.</p> ---ldx]]-- - -function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - -- local head, n = delete_till_stop(head,start,stop) - local startchar = start.char - local subtables = currentlookup.subtables - local lookupname = subtables[1] - local replacements = lookuphash[lookupname] - if not replacements then - if trace_bugs then - logwarning("%s: no multiple hits",cref(kind,chainname,chainlookupname,lookupname)) - end - else - replacements = replacements[startchar] - if not replacements or replacement == "" then - if trace_bugs then - logwarning("%s: no multiple for %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar)) - end - else - if trace_multiples then - logprocess("%s: replacing %s by multiple characters %s",cref(kind,chainname,chainlookupname,lookupname),gref(startchar),gref(replacements)) - end - return multiple_glyphs(head,start,replacements,currentlookup.flags[1]) - end - end - return head, start, false -end - -chainmores.gsub_multiple = chainprocs.gsub_multiple - ---[[ldx-- -<p>Here we replace start by new glyph. First we delete the rest of the match.</p> ---ldx]]-- - --- char_1 mark_1 -> char_x mark_1 (ignore marks) --- char_1 mark_1 -> char_x - --- to be checked: do we always have just one glyph? --- we can also have alternates for marks --- marks come last anyway --- are there cases where we need to delete the mark - -function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local current = start - local subtables = currentlookup.subtables - local value = featurevalue == true and tfmdata.shared.features[kind] or featurevalue - while current do - if current.id == glyph_code then -- is this check needed? - local currentchar = current.char - local lookupname = subtables[1] - local alternatives = lookuphash[lookupname] - if not alternatives then - if trace_bugs then - logwarning("%s: no alternative hit",cref(kind,chainname,chainlookupname,lookupname)) - end - else - alternatives = alternatives[currentchar] - if alternatives then - local choice, comment = get_alternative_glyph(current,alternatives,value,trace_alternatives) - if choice then - if trace_alternatives then - logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment) - end - start.char = choice - else - if trace_alternatives then - logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment) - end - end - elseif trace_bugs then - logwarning("%s: no alternative for %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(currentchar),comment) - end - end - return head, start, true - elseif current == stop then - break - else - current = current.next - end - end - return head, start, false -end - -chainmores.gsub_alternate = chainprocs.gsub_alternate - ---[[ldx-- -<p>When we replace ligatures we use a helper that handles the marks. I might change -this function (move code inline and handle the marks by a separate function). We -assume rather stupid ligatures (no complex disc nodes).</p> ---ldx]]-- - -function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex) - local startchar = start.char - local subtables = currentlookup.subtables - local lookupname = subtables[1] - local ligatures = lookuphash[lookupname] - if not ligatures then - if trace_bugs then - logwarning("%s: no ligature hits",cref(kind,chainname,chainlookupname,lookupname,chainindex)) - end - else - ligatures = ligatures[startchar] - if not ligatures then - if trace_bugs then - logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) - end - else - local s = start.next - local discfound = false - local last = stop - local nofreplacements = 0 - local skipmark = currentlookup.flags[1] - while s do - local id = s.id - if id == disc_code then - s = s.next - discfound = true - else - local schar = s.char - if skipmark and marks[schar] then -- marks - s = s.next - else - local lg = ligatures[schar] - if lg then - ligatures, last, nofreplacements = lg, s, nofreplacements + 1 - if s == stop then - break - else - s = s.next - end - else - break - end - end - end - end - local l2 = ligatures.ligature - if l2 then - if chainindex then - stop = last - end - if trace_ligatures then - if start == stop then - logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2)) - else - logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2)) - end - end - head, start = toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound) - return head, start, true, nofreplacements - elseif trace_bugs then - if start == stop then - logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar)) - else - logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char)) - end - end - end - end - return head, start, false, 0 -end - -chainmores.gsub_ligature = chainprocs.gsub_ligature - -function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar = start.char - if marks[markchar] then - local subtables = currentlookup.subtables - local lookupname = subtables[1] - local markanchors = lookuphash[lookupname] - if markanchors then - markanchors = markanchors[markchar] - end - if markanchors then - local base = start.prev -- [glyph] [start=mark] - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then - local basechar = base.char - if marks[basechar] then - while true do - base = base.prev - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then - basechar = base.char - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s",pref(kind,lookupname),gref(markchar)) - end - return head, start, false - end - end - end - local baseanchors = descriptions[basechar].anchors - if baseanchors then - local baseanchors = baseanchors['basechar'] - if baseanchors then - local al = anchorlookups[lookupname] - for anchor,ba in next, baseanchors do - if al[anchor] then - local ma = markanchors[anchor] - if ma then - local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basechar %s => (%p,%p)", - cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head, start, true - end - end - end - if trace_bugs then - logwarning("%s, no matching anchors for mark %s and base %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar)) - end - end - end - elseif trace_bugs then - logwarning("%s: prev node is no char",cref(kind,chainname,chainlookupname,lookupname)) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) - end - return head, start, false -end - -function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar = start.char - if marks[markchar] then - local subtables = currentlookup.subtables - local lookupname = subtables[1] - local markanchors = lookuphash[lookupname] - if markanchors then - markanchors = markanchors[markchar] - end - if markanchors then - local base = start.prev -- [glyph] [optional marks] [start=mark] - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then - local basechar = base.char - if marks[basechar] then - while true do - base = base.prev - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then - basechar = base.char - if not marks[basechar] then - break - end - else - if trace_bugs then - logwarning("%s: no base for mark %s",cref(kind,chainname,chainlookupname,lookupname),markchar) - end - return head, start, false - end - end - end - -- todo: like marks a ligatures hash - local index = start[a_ligacomp] - local baseanchors = descriptions[basechar].anchors - if baseanchors then - local baseanchors = baseanchors['baselig'] - if baseanchors then - local al = anchorlookups[lookupname] - for anchor,ba in next, baseanchors do - if al[anchor] then - local ma = markanchors[anchor] - if ma then - ba = ba[index] - if ba then - local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma) -- index - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to baselig %s at index %s => (%p,%p)", - cref(kind,chainname,chainlookupname,lookupname),anchor,a or bound,gref(markchar),gref(basechar),index,dx,dy) - end - return head, start, true - end - end - end - end - if trace_bugs then - logwarning("%s: no matching anchors for mark %s and baselig %s",cref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar)) - end - end - end - elseif trace_bugs then - logwarning("feature %s, lookup %s: prev node is no char",kind,lookupname) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar)) - end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) - end - return head, start, false -end - -function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local markchar = start.char - if marks[markchar] then - -- local alreadydone = markonce and start[a_markmark] - -- if not alreadydone then - -- local markanchors = descriptions[markchar].anchors markanchors = markanchors and markanchors.mark - local subtables = currentlookup.subtables - local lookupname = subtables[1] - local markanchors = lookuphash[lookupname] - if markanchors then - markanchors = markanchors[markchar] - end - if markanchors then - local base = start.prev -- [glyph] [basemark] [start=mark] - local slc = start[a_ligacomp] - if slc then -- a rather messy loop ... needs checking with husayni - while base do - local blc = base[a_ligacomp] - if blc and blc ~= slc then - base = base.prev - else - break - end - end - end - if base and base.id == glyph_code and base.font == currentfont and base.subtype<256 then -- subtype test can go - local basechar = base.char - local baseanchors = descriptions[basechar].anchors - if baseanchors then - baseanchors = baseanchors['basemark'] - if baseanchors then - local al = anchorlookups[lookupname] - for anchor,ba in next, baseanchors do - if al[anchor] then - local ma = markanchors[anchor] - if ma then - local dx, dy, bound = setmark(start,base,tfmdata.parameters.factor,rlmode,ba,ma,true) - if trace_marks then - logprocess("%s, anchor %s, bound %s: anchoring mark %s to basemark %s => (%p,%p)", - cref(kind,chainname,chainlookupname,lookupname),anchor,bound,gref(markchar),gref(basechar),dx,dy) - end - return head, start, true - end - end - end - if trace_bugs then - logwarning("%s: no matching anchors for mark %s and basemark %s",gref(kind,chainname,chainlookupname,lookupname),gref(markchar),gref(basechar)) - end - end - end - elseif trace_bugs then - logwarning("%s: prev node is no mark",cref(kind,chainname,chainlookupname,lookupname)) - end - elseif trace_bugs then - logwarning("%s: mark %s has no anchors",cref(kind,chainname,chainlookupname,lookupname),gref(markchar)) - end - -- elseif trace_marks and trace_details then - -- logprocess("%s, mark %s is already bound (n=%s), ignoring mark2mark",pref(kind,lookupname),gref(markchar),alreadydone) - -- end - elseif trace_bugs then - logwarning("%s: mark %s is no mark",cref(kind,chainname,chainlookupname),gref(markchar)) - end - return head, start, false -end - -function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname) - local alreadydone = cursonce and start[a_cursbase] - if not alreadydone then - local startchar = start.char - local subtables = currentlookup.subtables - local lookupname = subtables[1] - local exitanchors = lookuphash[lookupname] - if exitanchors then - exitanchors = exitanchors[startchar] - end - if exitanchors then - local done = false - if marks[startchar] then - if trace_cursive then - logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar)) - end - else - local nxt = start.next - while not done and nxt and nxt.id == glyph_code and nxt.font == currentfont and nxt.subtype<256 do - local nextchar = nxt.char - if marks[nextchar] then - -- should not happen (maybe warning) - nxt = nxt.next - else - local entryanchors = descriptions[nextchar] - if entryanchors then - entryanchors = entryanchors.anchors - if entryanchors then - entryanchors = entryanchors['centry'] - if entryanchors then - local al = anchorlookups[lookupname] - for anchor, entry in next, entryanchors do - if al[anchor] then - local exit = exitanchors[anchor] - if exit then - local dx, dy, bound = setcursive(start,nxt,tfmdata.parameters.factor,rlmode,exit,entry,characters[startchar],characters[nextchar]) - if trace_cursive then - logprocess("%s: moving %s to %s cursive (%p,%p) using anchor %s and bound %s in rlmode %s",pref(kind,lookupname),gref(startchar),gref(nextchar),dx,dy,anchor,bound,rlmode) - end - done = true - break - end - end - end - end - end - elseif trace_bugs then - -- logwarning("%s: char %s is missing in font",pref(kind,lookupname),gref(startchar)) - onetimemessage(currentfont,startchar,"no entry anchors",report_fonts) - end - break - end - end - end - return head, start, done - else - if trace_cursive and trace_details then - logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone) - end - return head, start, false - end - end - return head, start, false -end - -function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) - -- untested .. needs checking for the new model - local startchar = start.char - local subtables = currentlookup.subtables - local lookupname = subtables[1] - local kerns = lookuphash[lookupname] - if kerns then - kerns = kerns[startchar] -- needed ? - if kerns then - local dx, dy, w, h = setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar]) - if trace_kerns then - logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),dx,dy,w,h) - end - end - end - return head, start, false -end - -chainmores.gpos_single = chainprocs.gpos_single -- okay? - --- when machines become faster i will make a shared function - -function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence) - local snext = start.next - if snext then - local startchar = start.char - local subtables = currentlookup.subtables - local lookupname = subtables[1] - local kerns = lookuphash[lookupname] - if kerns then - kerns = kerns[startchar] - if kerns then - local lookuptype = lookuptypes[lookupname] - local prev, done = start, false - local factor = tfmdata.parameters.factor - while snext and snext.id == glyph_code and snext.font == currentfont and snext.subtype<256 do - local nextchar = snext.char - local krn = kerns[nextchar] - if not krn and marks[nextchar] then - prev = snext - snext = snext.next - else - if not krn then - -- skip - elseif type(krn) == "table" then - if lookuptype == "pair" then - local a, b = krn[2], krn[3] - if a and #a > 0 then - local startchar = start.char - local x, y, w, h = setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar]) - if trace_kerns then - logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) - end - end - if b and #b > 0 then - local startchar = start.char - local x, y, w, h = setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar]) - if trace_kerns then - logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h) - end - end - else - report_process("%s: check this out (old kern stuff)",cref(kind,chainname,chainlookupname)) - local a, b = krn[2], krn[6] - if a and a ~= 0 then - local k = setkern(snext,factor,rlmode,a) - if trace_kerns then - logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) - end - end - if b and b ~= 0 then - logwarning("%s: ignoring second kern xoff %s",cref(kind,chainname,chainlookupname),b*factor) - end - end - done = true - elseif krn ~= 0 then - local k = setkern(snext,factor,rlmode,krn) - if trace_kerns then - logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar)) - end - done = true - end - break - end - end - return head, start, done - end - end - end - return head, start, false -end - -chainmores.gpos_pair = chainprocs.gpos_pair -- okay? - --- what pointer to return, spec says stop --- to be discussed ... is bidi changer a space? --- elseif char == zwnj and sequence[n][32] then -- brrr - --- somehow l or f is global --- we don't need to pass the currentcontext, saves a bit --- make a slow variant then can be activated but with more tracing - -local function show_skip(kind,chainname,char,ck,class) - if ck[9] then - logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a, %a => %a",cref(kind,chainname),gref(char),class,ck[1],ck[2],ck[9],ck[10]) - else - logwarning("%s: skipping char %s, class %a, rule %a, lookuptype %a",cref(kind,chainname),gref(char),class,ck[1],ck[2]) - end -end - -local function normal_handle_contextchain(head,start,kind,chainname,contexts,sequence,lookuphash) - -- local rule, lookuptype, sequence, f, l, lookups = ck[1], ck[2] ,ck[3], ck[4], ck[5], ck[6] - local flags = sequence.flags - local done = false - local skipmark = flags[1] - local skipligature = flags[2] - local skipbase = flags[3] - local someskip = skipmark or skipligature or skipbase -- could be stored in flags for a fast test (hm, flags could be false !) - local markclass = sequence.markclass -- todo, first we need a proper test - local skipped = false - for k=1,#contexts do - local match = true - local current = start - local last = start - local ck = contexts[k] - local seq = ck[3] - local s = #seq - -- f..l = mid string - if s == 1 then - -- never happens - match = current.id == glyph_code and current.font == currentfont and current.subtype<256 and seq[1][current.char] - else - -- maybe we need a better space check (maybe check for glue or category or combination) - -- we cannot optimize for n=2 because there can be disc nodes - local f, l = ck[4], ck[5] - -- current match - if f == 1 and f == l then -- current only - -- already a hit - -- match = true - else -- before/current/after | before/current | current/after - -- no need to test first hit (to be optimized) - if f == l then -- new, else last out of sync (f is > 1) - -- match = true - else - local n = f + 1 - last = last.next - while n <= l do - if last then - local id = last.id - if id == glyph_code then - if last.font == currentfont and last.subtype<256 then - local char = last.char - local ccd = descriptions[char] - if ccd then - local class = ccd.class - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - skipped = true - if trace_skips then - show_skip(kind,chainname,char,ck,class) - end - last = last.next - elseif seq[n][char] then - if n < l then - last = last.next - end - n = n + 1 - else - match = false - break - end - else - match = false - break - end - else - match = false - break - end - elseif id == disc_code then - last = last.next - else - match = false - break - end - else - match = false - break - end - end - end - end - -- before - if match and f > 1 then - local prev = start.prev - if prev then - local n = f-1 - while n >= 1 do - if prev then - local id = prev.id - if id == glyph_code then - if prev.font == currentfont and prev.subtype<256 then -- normal char - local char = prev.char - local ccd = descriptions[char] - if ccd then - local class = ccd.class - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - skipped = true - if trace_skips then - show_skip(kind,chainname,char,ck,class) - end - elseif seq[n][char] then - n = n -1 - else - match = false - break - end - else - match = false - break - end - else - match = false - break - end - elseif id == disc_code then - -- skip 'm - elseif seq[n][32] then - n = n -1 - else - match = false - break - end - prev = prev.prev - elseif seq[n][32] then -- somewhat special, as zapfino can have many preceding spaces - n = n -1 - else - match = false - break - end - end - elseif f == 2 then - match = seq[1][32] - else - for n=f-1,1 do - if not seq[n][32] then - match = false - break - end - end - end - end - -- after - if match and s > l then - local current = last and last.next - if current then - -- removed optimization for s-l == 1, we have to deal with marks anyway - local n = l + 1 - while n <= s do - if current then - local id = current.id - if id == glyph_code then - if current.font == currentfont and current.subtype<256 then -- normal char - local char = current.char - local ccd = descriptions[char] - if ccd then - local class = ccd.class - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - skipped = true - if trace_skips then - show_skip(kind,chainname,char,ck,class) - end - elseif seq[n][char] then - n = n + 1 - else - match = false - break - end - else - match = false - break - end - else - match = false - break - end - elseif id == disc_code then - -- skip 'm - elseif seq[n][32] then -- brrr - n = n + 1 - else - match = false - break - end - current = current.next - elseif seq[n][32] then - n = n + 1 - else - match = false - break - end - end - elseif s-l == 1 then - match = seq[s][32] - else - for n=l+1,s do - if not seq[n][32] then - match = false - break - end - end - end - end - end - if match then - -- ck == currentcontext - if trace_contexts then - local rule, lookuptype, f, l = ck[1], ck[2], ck[4], ck[5] - local char = start.char - if ck[9] then - logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a", - cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10]) - else - logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a", - cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype) - end - end - local chainlookups = ck[6] - if chainlookups then - local nofchainlookups = #chainlookups - -- we can speed this up if needed - if nofchainlookups == 1 then - local chainlookupname = chainlookups[1] - local chainlookup = lookuptable[chainlookupname] - if chainlookup then - local cp = chainprocs[chainlookup.type] - if cp then - local ok - head, start, ok = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,nil,sequence) - if ok then - done = true - end - else - logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type) - end - else -- shouldn't happen - logprocess("%s is not yet supported",cref(kind,chainname,chainlookupname)) - end - else - local i = 1 - repeat - if skipped then - while true do - local char = start.char - local ccd = descriptions[char] - if ccd then - local class = ccd.class - if class == skipmark or class == skipligature or class == skipbase or (markclass and class == "mark" and not markclass[char]) then - start = start.next - else - break - end - else - break - end - end - end - local chainlookupname = chainlookups[i] - local chainlookup = lookuptable[chainlookupname] - if not chainlookup then - -- okay, n matches, < n replacements - i = i + 1 - else - local cp = chainmores[chainlookup.type] - if not cp then - -- actually an error - logprocess("%s: %s is not yet supported",cref(kind,chainname,chainlookupname),chainlookup.type) - i = i + 1 - else - local ok, n - head, start, ok, n = cp(head,start,last,kind,chainname,ck,lookuphash,chainlookup,chainlookupname,i,sequence) - -- messy since last can be changed ! - if ok then - done = true - -- skip next one(s) if ligature - i = i + (n or 1) - else - i = i + 1 - end - end - end - if start then - start = start.next - else - -- weird - end - until i > nofchainlookups - end - else - local replacements = ck[7] - if replacements then - head, start, done = chainprocs.reversesub(head,start,last,kind,chainname,ck,lookuphash,replacements) -- sequence - else - done = true -- can be meant to be skipped - if trace_contexts then - logprocess("%s: skipping match",cref(kind,chainname)) - end - end - end - end - end - return head, start, done -end - --- Because we want to keep this elsewhere (an because speed is less an issue) we --- pass the font id so that the verbose variant can access the relevant helper tables. - -local verbose_handle_contextchain = function(font,...) - logwarning("no verbose handler installed, reverting to 'normal'") - otf.setcontextchain() - return normal_handle_contextchain(...) -end - -otf.chainhandlers = { - normal = normal_handle_contextchain, - verbose = verbose_handle_contextchain, -} - -function otf.setcontextchain(method) - if not method or method == "normal" or not otf.chainhandlers[method] then - if handlers.contextchain then -- no need for a message while making the format - logwarning("installing normal contextchain handler") - end - handlers.contextchain = normal_handle_contextchain - else - logwarning("installing contextchain handler %a",method) - local handler = otf.chainhandlers[method] - handlers.contextchain = function(...) - return handler(currentfont,...) -- hm, get rid of ... - end - end - handlers.gsub_context = handlers.contextchain - handlers.gsub_contextchain = handlers.contextchain - handlers.gsub_reversecontextchain = handlers.contextchain - handlers.gpos_contextchain = handlers.contextchain - handlers.gpos_context = handlers.contextchain -end - -otf.setcontextchain() - -local missing = { } -- we only report once - -local function logprocess(...) - if trace_steps then - registermessage(...) - end - report_process(...) -end - -local logwarning = report_process - -local function report_missing_cache(typ,lookup) - local f = missing[currentfont] if not f then f = { } missing[currentfont] = f end - local t = f[typ] if not t then t = { } f[typ] = t end - if not t[lookup] then - t[lookup] = true - logwarning("missing cache for lookup %a, type %a, font %a, name %a",lookup,typ,currentfont,tfmdata.properties.fullname) - end -end - -local resolved = { } -- we only resolve a font,script,language pair once - --- todo: pass all these 'locals' in a table - -local lookuphashes = { } - -setmetatableindex(lookuphashes, function(t,font) - local lookuphash = fontdata[font].resources.lookuphash - if not lookuphash or not next(lookuphash) then - lookuphash = false - end - t[font] = lookuphash - return lookuphash -end) - --- fonts.hashes.lookups = lookuphashes - -local autofeatures = fonts.analyzers.features -- was: constants - -local function initialize(sequence,script,language,enabled) - local features = sequence.features - if features then - for kind, scripts in next, features do - local valid = enabled[kind] - if valid then - local languages = scripts[script] or scripts[wildcard] - if languages and (languages[language] or languages[wildcard]) then - return { valid, autofeatures[kind] or false, sequence.chain or 0, kind, sequence } - end - end - end - end - return false -end - -function otf.dataset(tfmdata,font) -- generic variant, overloaded in context - local shared = tfmdata.shared - local properties = tfmdata.properties - local language = properties.language or "dflt" - local script = properties.script or "dflt" - local enabled = shared.features - local res = resolved[font] - if not res then - res = { } - resolved[font] = res - end - local rs = res[script] - if not rs then - rs = { } - res[script] = rs - end - local rl = rs[language] - if not rl then - rl = { - -- indexed but we can also add specific data by key - } - rs[language] = rl - local sequences = tfmdata.resources.sequences --- setmetatableindex(rl, function(t,k) --- if type(k) == "number" then --- local v = enabled and initialize(sequences[k],script,language,enabled) --- t[k] = v --- return v --- end --- end) -for s=1,#sequences do - local v = enabled and initialize(sequences[s],script,language,enabled) - if v then - rl[#rl+1] = v - end -end - end - return rl -end - --- elseif id == glue_code then --- if p[5] then -- chain --- local pc = pp[32] --- if pc then --- start, ok = start, false -- p[1](start,kind,p[2],pc,p[3],p[4]) --- if ok then --- done = true --- end --- if start then start = start.next end --- else --- start = start.next --- end --- else --- start = start.next --- end - --- there will be a new direction parser (pre-parsed etc) - --- less bytecode: 290 -> 254 --- --- attr = attr or false --- --- local a = getattr(start,0) --- if (a == attr and (not attribute or getattr(start,a_state) == attribute)) or (not attribute or getattr(start,a_state) == attribute) then --- -- the action --- end - -local function featuresprocessor(head,font,attr) - - local lookuphash = lookuphashes[font] -- we can also check sequences here - - if not lookuphash then - return head, false - end - - if trace_steps then - checkstep(head) - end - - tfmdata = fontdata[font] - descriptions = tfmdata.descriptions - characters = tfmdata.characters - resources = tfmdata.resources - - marks = resources.marks - anchorlookups = resources.lookup_to_anchor - lookuptable = resources.lookups - lookuptypes = resources.lookuptypes - - currentfont = font - rlmode = 0 - - local sequences = resources.sequences - local done = false - local datasets = otf.dataset(tfmdata,font,attr) - - local dirstack = { } -- could move outside function - - -- We could work on sub start-stop ranges instead but I wonder if there is that - -- much speed gain (experiments showed that it made not much sense) and we need - -- to keep track of directions anyway. Also at some point I want to play with - -- font interactions and then we do need the full sweeps. - - -- Keeping track of the headnode is needed for devanagari (I generalized it a bit - -- so that multiple cases are also covered.) - - for s=1,#datasets do - local dataset = datasets[s] - featurevalue = dataset[1] -- todo: pass to function instead of using a global - - local sequence = dataset[5] -- sequences[s] -- also dataset[5] - local rlparmode = 0 - local topstack = 0 - local success = false - local attribute = dataset[2] - local chain = dataset[3] -- sequence.chain or 0 - local typ = sequence.type - local subtables = sequence.subtables - if chain < 0 then - -- this is a limited case, no special treatments like 'init' etc - local handler = handlers[typ] - -- we need to get rid of this slide! probably no longer needed in latest luatex - local start = find_node_tail(head) -- slow (we can store tail because there's always a skip at the end): todo - while start do - local id = start.id - if id == glyph_code then - if start.font == font and start.subtype<256 then - local a = start[0] - if a then - a = a == attr - else - a = true - end - if a then - for i=1,#subtables do - local lookupname = subtables[i] - local lookupcache = lookuphash[lookupname] - if lookupcache then - local lookupmatch = lookupcache[start.char] - if lookupmatch then - head, start, success = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) - if success then - break - end - end - else - report_missing_cache(typ,lookupname) - end - end - if start then start = start.prev end - else - start = start.prev - end - else - start = start.prev - end - else - start = start.prev - end - end - else - local handler = handlers[typ] - local ns = #subtables - local start = head -- local ? - rlmode = 0 -- to be checked ? - if ns == 1 then -- happens often - local lookupname = subtables[1] - local lookupcache = lookuphash[lookupname] - if not lookupcache then -- also check for empty cache - report_missing_cache(typ,lookupname) - else - - local function subrun(start) - -- mostly for gsub, gpos would demand a more clever approach - local head = start - local done = false - while start do - local id = start.id - if id == glyph_code and start.font == font and start.subtype <256 then - local a = start[0] - if a then - a = (a == attr) and (not attribute or start[a_state] == attribute) - else - a = not attribute or start[a_state] == attribute - end - if a then - local lookupmatch = lookupcache[start.char] - if lookupmatch then - -- sequence kan weg - local ok - head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) - if ok then - done = true - end - end - if start then start = start.next end - else - start = start.next - end - else - start = start.next - end - end - if done then - success = true - return head - end - end - - local function kerndisc(disc) -- we can assume that prev and next are glyphs - local prev = disc.prev - local next = disc.next - if prev and next then - prev.next = next - -- next.prev = prev - local a = prev[0] - if a then - a = (a == attr) and (not attribute or prev[a_state] == attribute) - else - a = not attribute or prev[a_state] == attribute - end - if a then - local lookupmatch = lookupcache[prev.char] - if lookupmatch then - -- sequence kan weg - local h, d, ok = handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) - if ok then - done = true - success = true - end - end - end - prev.next = disc - -- next.prev = disc - end - return next - end - - while start do - local id = start.id - if id == glyph_code then - if start.font == font and start.subtype<256 then - local a = start[0] - if a then - a = (a == attr) and (not attribute or start[a_state] == attribute) - else - a = not attribute or start[a_state] == attribute - end - if a then - local lookupmatch = lookupcache[start.char] - if lookupmatch then - -- sequence kan weg - local ok - head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1) - if ok then - success = true - end - end - if start then start = start.next end - else - start = start.next - end - else - start = start.next - end - elseif id == disc_code then - -- mostly for gsub - if start.subtype == discretionary_code then - local pre = start.pre - if pre then - local new = subrun(pre) - if new then start.pre = new end - end - local post = start.post - if post then - local new = subrun(post) - if new then start.post = new end - end - local replace = start.replace - if replace then - local new = subrun(replace) - if new then start.replace = new end - end -elseif typ == "gpos_single" or typ == "gpos_pair" then - kerndisc(start) - end - start = start.next - elseif id == whatsit_code then -- will be function - local subtype = start.subtype - if subtype == dir_code then - local dir = start.dir - if dir == "+TRT" or dir == "+TLT" then - topstack = topstack + 1 - dirstack[topstack] = dir - elseif dir == "-TRT" or dir == "-TLT" then - topstack = topstack - 1 - end - local newdir = dirstack[topstack] - if newdir == "+TRT" then - rlmode = -1 - elseif newdir == "+TLT" then - rlmode = 1 - else - rlmode = rlparmode - end - if trace_directions then - report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir) - end - elseif subtype == localpar_code then - local dir = start.dir - if dir == "TRT" then - rlparmode = -1 - elseif dir == "TLT" then - rlparmode = 1 - else - rlparmode = 0 - end - -- one might wonder if the par dir should be looked at, so we might as well drop the next line - rlmode = rlparmode - if trace_directions then - report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode) - end - end - start = start.next - elseif id == math_code then - start = end_of_math(start).next - else - start = start.next - end - end - end - else - - local function subrun(start) - -- mostly for gsub, gpos would demand a more clever approach - local head = start - local done = false - while start do - local id = start.id - if id == glyph_code and start.id == font and start.subtype <256 then - local a = start[0] - if a then - a = (a == attr) and (not attribute or start[a_state] == attribute) - else - a = not attribute or start[a_state] == attribute - end - if a then - for i=1,ns do - local lookupname = subtables[i] - local lookupcache = lookuphash[lookupname] - if lookupcache then - local lookupmatch = lookupcache[start.char] - if lookupmatch then - -- we could move all code inline but that makes things even more unreadable - local ok - head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) - if ok then - done = true - break - elseif not start then - -- don't ask why ... shouldn't happen - break - end - end - else - report_missing_cache(typ,lookupname) - end - end - if start then start = start.next end - else - start = start.next - end - else - start = start.next - end - end - if done then - success = true - return head - end - end - - local function kerndisc(disc) -- we can assume that prev and next are glyphs - local prev = disc.prev - local next = disc.next - if prev and next then - prev.next = next - -- next.prev = prev - local a = prev[0] - if a then - a = (a == attr) and (not attribute or prev[a_state] == attribute) - else - a = not attribute or prev[a_state] == attribute - end - if a then - for i=1,ns do - local lookupname = subtables[i] - local lookupcache = lookuphash[lookupname] - if lookupcache then - local lookupmatch = lookupcache[prev.char] - if lookupmatch then - -- we could move all code inline but that makes things even more unreadable - local h, d, ok = handler(head,prev,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) - if ok then - done = true - break - end - end - else - report_missing_cache(typ,lookupname) - end - end - end - prev.next = disc - -- next.prev = disc - end - return next - end - - while start do - local id = start.id - if id == glyph_code then - if start.font == font and start.subtype<256 then - local a = start[0] - if a then - a = (a == attr) and (not attribute or start[a_state] == attribute) - else - a = not attribute or start[a_state] == attribute - end - if a then - for i=1,ns do - local lookupname = subtables[i] - local lookupcache = lookuphash[lookupname] - if lookupcache then - local lookupmatch = lookupcache[start.char] - if lookupmatch then - -- we could move all code inline but that makes things even more unreadable - local ok - head, start, ok = handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i) - if ok then - success = true - break - elseif not start then - -- don't ask why ... shouldn't happen - break - end - end - else - report_missing_cache(typ,lookupname) - end - end - if start then start = start.next end - else - start = start.next - end - else - start = start.next - end - elseif id == disc_code then - -- mostly for gsub - if start.subtype == discretionary_code then - local pre = start.pre - if pre then - local new = subrun(pre) - if new then start.pre = new end - end - local post = start.post - if post then - local new = subrun(post) - if new then start.post = new end - end - local replace = start.replace - if replace then - local new = subrun(replace) - if new then start.replace = new end - end -elseif typ == "gpos_single" or typ == "gpos_pair" then - kerndisc(start) - end - start = start.next - elseif id == whatsit_code then - local subtype = start.subtype - if subtype == dir_code then - local dir = start.dir - if dir == "+TRT" or dir == "+TLT" then - topstack = topstack + 1 - dirstack[topstack] = dir - elseif dir == "-TRT" or dir == "-TLT" then - topstack = topstack - 1 - end - local newdir = dirstack[topstack] - if newdir == "+TRT" then - rlmode = -1 - elseif newdir == "+TLT" then - rlmode = 1 - else - rlmode = rlparmode - end - if trace_directions then - report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir) - end - elseif subtype == localpar_code then - local dir = start.dir - if dir == "TRT" then - rlparmode = -1 - elseif dir == "TLT" then - rlparmode = 1 - else - rlparmode = 0 - end - rlmode = rlparmode - if trace_directions then - report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode) - end - end - start = start.next - elseif id == math_code then - start = end_of_math(start).next - else - start = start.next - end - end - end - end - if success then - done = true - end - if trace_steps then -- ? - registerstep(head) - end - end - return head, done -end - -local function generic(lookupdata,lookupname,unicode,lookuphash) - local target = lookuphash[lookupname] - if target then - target[unicode] = lookupdata - else - lookuphash[lookupname] = { [unicode] = lookupdata } - end -end - -local action = { - - substitution = generic, - multiple = generic, - alternate = generic, - position = generic, - - ligature = function(lookupdata,lookupname,unicode,lookuphash) - local target = lookuphash[lookupname] - if not target then - target = { } - lookuphash[lookupname] = target - end - for i=1,#lookupdata do - local li = lookupdata[i] - local tu = target[li] - if not tu then - tu = { } - target[li] = tu - end - target = tu - end - target.ligature = unicode - end, - - pair = function(lookupdata,lookupname,unicode,lookuphash) - local target = lookuphash[lookupname] - if not target then - target = { } - lookuphash[lookupname] = target - end - local others = target[unicode] - local paired = lookupdata[1] - if others then - others[paired] = lookupdata - else - others = { [paired] = lookupdata } - target[unicode] = others - end - end, - -} - -local function prepare_lookups(tfmdata) - - local rawdata = tfmdata.shared.rawdata - local resources = rawdata.resources - local lookuphash = resources.lookuphash - local anchor_to_lookup = resources.anchor_to_lookup - local lookup_to_anchor = resources.lookup_to_anchor - local lookuptypes = resources.lookuptypes - local characters = tfmdata.characters - local descriptions = tfmdata.descriptions - - -- we cannot free the entries in the descriptions as sometimes we access - -- then directly (for instance anchors) ... selectively freeing does save - -- much memory as it's only a reference to a table and the slot in the - -- description hash is not freed anyway - - for unicode, character in next, characters do -- we cannot loop over descriptions ! - - local description = descriptions[unicode] - - if description then - - local lookups = description.slookups - if lookups then - for lookupname, lookupdata in next, lookups do - action[lookuptypes[lookupname]](lookupdata,lookupname,unicode,lookuphash) - end - end - - local lookups = description.mlookups - if lookups then - for lookupname, lookuplist in next, lookups do - local lookuptype = lookuptypes[lookupname] - for l=1,#lookuplist do - local lookupdata = lookuplist[l] - action[lookuptype](lookupdata,lookupname,unicode,lookuphash) - end - end - end - - local list = description.kerns - if list then - for lookup, krn in next, list do -- ref to glyph, saves lookup - local target = lookuphash[lookup] - if target then - target[unicode] = krn - else - lookuphash[lookup] = { [unicode] = krn } - end - end - end - - local list = description.anchors - if list then - for typ, anchors in next, list do -- types - if typ == "mark" or typ == "cexit" then -- or entry? - for name, anchor in next, anchors do - local lookups = anchor_to_lookup[name] - if lookups then - for lookup, _ in next, lookups do - local target = lookuphash[lookup] - if target then - target[unicode] = anchors - else - lookuphash[lookup] = { [unicode] = anchors } - end - end - end - end - end - end - end - - end - - end - -end - -local function split(replacement,original) - local result = { } - for i=1,#replacement do - result[original[i]] = replacement[i] - end - return result -end - -local valid = { - coverage = { chainsub = true, chainpos = true, contextsub = true }, - reversecoverage = { reversesub = true }, - glyphs = { chainsub = true, chainpos = true }, -} - -local function prepare_contextchains(tfmdata) - local rawdata = tfmdata.shared.rawdata - local resources = rawdata.resources - local lookuphash = resources.lookuphash - local lookups = rawdata.lookups - if lookups then - for lookupname, lookupdata in next, rawdata.lookups do - local lookuptype = lookupdata.type - if lookuptype then - local rules = lookupdata.rules - if rules then - local format = lookupdata.format - local validformat = valid[format] - if not validformat then - report_prepare("unsupported format %a",format) - elseif not validformat[lookuptype] then - -- todo: dejavu-serif has one (but i need to see what use it has) - report_prepare("unsupported format %a, lookuptype %a, lookupname %a",format,lookuptype,lookupname) - else - local contexts = lookuphash[lookupname] - if not contexts then - contexts = { } - lookuphash[lookupname] = contexts - end - local t, nt = { }, 0 - for nofrules=1,#rules do - local rule = rules[nofrules] - local current = rule.current - local before = rule.before - local after = rule.after - local replacements = rule.replacements - local sequence = { } - local nofsequences = 0 - -- Eventually we can store start, stop and sequence in the cached file - -- but then less sharing takes place so best not do that without a lot - -- of profiling so let's forget about it. - if before then - for n=1,#before do - nofsequences = nofsequences + 1 - sequence[nofsequences] = before[n] - end - end - local start = nofsequences + 1 - for n=1,#current do - nofsequences = nofsequences + 1 - sequence[nofsequences] = current[n] - end - local stop = nofsequences - if after then - for n=1,#after do - nofsequences = nofsequences + 1 - sequence[nofsequences] = after[n] - end - end - if sequence[1] then - -- Replacements only happen with reverse lookups as they are single only. We - -- could pack them into current (replacement value instead of true) and then - -- use sequence[start] instead but it's somewhat ugly. - nt = nt + 1 - t[nt] = { nofrules, lookuptype, sequence, start, stop, rule.lookups, replacements } - for unic, _ in next, sequence[start] do - local cu = contexts[unic] - if not cu then - contexts[unic] = t - end - end - end - end - end - else - -- no rules - end - else - report_prepare("missing lookuptype for lookupname %a",lookupname) - end - end - end -end - --- we can consider lookuphash == false (initialized but empty) vs lookuphash == table - -local function featuresinitializer(tfmdata,value) - if true then -- value then - -- beware we need to use the topmost properties table - local rawdata = tfmdata.shared.rawdata - local properties = rawdata.properties - if not properties.initialized then - local starttime = trace_preparing and os.clock() - local resources = rawdata.resources - resources.lookuphash = resources.lookuphash or { } - prepare_contextchains(tfmdata) - prepare_lookups(tfmdata) - properties.initialized = true - if trace_preparing then - report_prepare("preparation time is %0.3f seconds for %a",os.clock()-starttime,tfmdata.properties.fullname) - end - end - end -end - -registerotffeature { - name = "features", - description = "features", - default = true, - initializers = { - position = 1, - node = featuresinitializer, - }, - processors = { - node = featuresprocessor, - } -} - --- This can be used for extra handlers, but should be used with care! - -otf.handlers = handlers diff --git a/tex/generic/context/luatex/luatex-fonts.lua b/tex/generic/context/luatex/luatex-fonts.lua index 5e5c9a4cf..7995be33e 100644 --- a/tex/generic/context/luatex/luatex-fonts.lua +++ b/tex/generic/context/luatex/luatex-fonts.lua @@ -210,9 +210,9 @@ if non_generic_context.luatex_fonts.skip_loading ~= true then loadmodule('font-oti.lua') loadmodule('font-otf.lua') loadmodule('font-otb.lua') - loadmodule('luatex-fonts-inj.lua') -- will be replaced (luatex >= .80) + loadmodule('node-inj.lua') -- will be replaced (luatex >= .70) loadmodule('font-ota.lua') - loadmodule('luatex-fonts-otn.lua') + loadmodule('font-otn.lua') loadmodule('font-otp.lua') -- optional loadmodule('luatex-fonts-lua.lua') loadmodule('font-def.lua') |