New upstream version 2019.20190605.51237
Norbert Preining
4 years ago
94 | 94 | docker run \ |
95 | 95 | -e TL_MAKE_FLAGS="${TL_MAKE_FLAGS}" \ |
96 | 96 | -v ${TRAVIS_BUILD_DIR}:/texlive -w /texlive \ |
97 | -it --rm alpine:3.1 sh -c \ | |
97 | -it --rm alpine:3.2 sh -c \ | |
98 | 98 | "apk update; apk add --no-progress bash gcc g++ make perl fontconfig-dev libx11-dev libxmu-dev libxaw-dev; ./Build -C" |
99 | 99 | - os: osx |
100 | 100 | osx_image: xcode7.3 |
0 | 2019-05-03 Karl Berry <karl@tug.org> | |
1 | ||
2 | * version.ac: 2020/dev. | |
3 | ||
4 | 0 | 2019-04-07 Karl Berry <karl@freefriends.org> |
5 | 1 | |
6 | 2 | * tardate.ac (tex_live_tardate): let's hope for 2019-04-07. |
1 | 1 | # Attempt to guess a canonical system name. |
2 | 2 | # Copyright 1992-2019 Free Software Foundation, Inc. |
3 | 3 | |
4 | timestamp='2019-04-28' | |
4 | timestamp='2019-03-04' | |
5 | 5 | |
6 | 6 | # This file is free software; you can redistribute it and/or modify it |
7 | 7 | # under the terms of the GNU General Public License as published by |
1467 | 1467 | #include <sys/types.h> |
1468 | 1468 | #include <sys/utsname.h> |
1469 | 1469 | #endif |
1470 | #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) | |
1471 | #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) | |
1472 | #include <signal.h> | |
1473 | #if defined(_SIZE_T_) || defined(SIGLOST) | |
1474 | #include <sys/utsname.h> | |
1475 | #endif | |
1476 | #endif | |
1477 | #endif | |
1478 | 1470 | main () |
1479 | 1471 | { |
1480 | 1472 | #if defined (sony) |
1562 | 1554 | printf ("vax-dec-bsd\n"); exit (0); |
1563 | 1555 | #endif |
1564 | 1556 | #else |
1565 | #if defined(_SIZE_T_) || defined(SIGLOST) | |
1566 | struct utsname un; | |
1567 | uname (&un); | |
1568 | printf ("vax-dec-ultrix%s\n", un.release); exit (0); | |
1569 | #else | |
1570 | 1557 | printf ("vax-dec-ultrix\n"); exit (0); |
1571 | #endif | |
1572 | 1558 | #endif |
1573 | 1559 | #endif |
1574 | 1560 | #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) |
1575 | 1561 | #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) |
1576 | #if defined(_SIZE_T_) || defined(SIGLOST) | |
1577 | struct utsname *un; | |
1578 | uname (&un); | |
1579 | printf ("mips-dec-ultrix%s\n", un.release); exit (0); | |
1562 | #include <signal.h> | |
1563 | #if defined(_SIZE_T_) /* >= ULTRIX4 */ | |
1564 | printf ("mips-dec-ultrix4\n"); exit (0); | |
1580 | 1565 | #else |
1581 | printf ("mips-dec-ultrix\n"); exit (0); | |
1566 | #if defined(ULTRIX3) || defined(ultrix3) || defined(SIGLOST) | |
1567 | printf ("mips-dec-ultrix3\n"); exit (0); | |
1568 | #endif | |
1582 | 1569 | #endif |
1583 | 1570 | #endif |
1584 | 1571 | #endif |
1246 | 1246 | | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ |
1247 | 1247 | | vax \ |
1248 | 1248 | | visium \ |
1249 | | w65 \ | |
1250 | | wasm32 | wasm64 \ | |
1249 | | w65 | wasm32 \ | |
1251 | 1250 | | we32k \ |
1252 | 1251 | | x86 | x86_64 | xc16x | xgate | xps100 \ |
1253 | 1252 | | xstormy16 | xtensa* \ |
1367 | 1366 | | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ |
1368 | 1367 | | skyos* | haiku* | rdos* | toppers* | drops* | es* \ |
1369 | 1368 | | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ |
1370 | | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi*) | |
1369 | | midnightbsd* | amdhsa* | unleashed* | emscripten*) | |
1371 | 1370 | # Remember, each alternative MUST END IN *, to match a version number. |
1372 | 1371 | ;; |
1373 | 1372 | qnx*) |
2 | 2 | % Load plain if necessary, i.e., if running under initex. |
3 | 3 | \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi |
4 | 4 | % |
5 | \def\texinfoversion{2019-04-12.13} | |
5 | \def\texinfoversion{2019-03-03.15} | |
6 | ||
6 | 7 | % |
7 | 8 | % Copyright 1985, 1986, 1988, 1990-2019 Free Software Foundation, Inc. |
8 | 9 | % |
385 | 386 | % take effect in \write's, yet the group defined by the \vbox ends |
386 | 387 | % before the \shipout runs. |
387 | 388 | % |
388 | \atdummies % don't expand commands in the output. | |
389 | \turnoffactive | |
389 | \indexdummies % don't expand commands in the output. | |
390 | \normalturnoffactive % \ in index entries must not stay \, e.g., if | |
391 | % the page break happens to be in the middle of an example. | |
392 | % We don't want .vr (or whatever) entries like this: | |
393 | % \entry{{\indexbackslash }acronym}{32}{\code {\acronym}} | |
394 | % "\acronym" won't work when it's read back in; | |
395 | % it needs to be | |
396 | % {\code {{\backslashcurfont }acronym} | |
390 | 397 | \shipout\vbox{% |
391 | 398 | % Do this early so pdf references go to the beginning of the page. |
392 | 399 | \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi |
447 | 454 | }% |
448 | 455 | } |
449 | 456 | |
450 | % First remove any @comment, then any @c comment. Pass the result on to | |
451 | % \argcheckspaces. | |
457 | % First remove any @comment, then any @c comment. Also remove a @texinfoc | |
458 | % comment (see \scanmacro for details). Pass the result on to \argcheckspaces. | |
452 | 459 | \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} |
453 | \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} | |
460 | \def\argremovec#1\c#2\ArgTerm{\argremovetexinfoc #1\texinfoc\ArgTerm} | |
461 | \def\argremovetexinfoc#1\texinfoc#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} | |
454 | 462 | |
455 | 463 | % Each occurrence of `\^^M' or `<space>\^^M' is replaced by a single space. |
456 | 464 | % |
1121 | 1129 | \fi |
1122 | 1130 | \fi |
1123 | 1131 | \fi |
1124 | ||
1125 | \newif\ifpdforxetex | |
1126 | \pdforxetexfalse | |
1127 | \ifpdf | |
1128 | \pdforxetextrue | |
1129 | \fi | |
1130 | \ifx\XeTeXrevision\thisisundefined\else | |
1131 | \pdforxetextrue | |
1132 | \fi | |
1133 | ||
1134 | 1132 | |
1135 | 1133 | % PDF uses PostScript string constants for the names of xref targets, |
1136 | 1134 | % for display in the outlines, and in other places. Thus, we have to |
2174 | 2172 | % A few fonts for @defun names and args. |
2175 | 2173 | \setfont\defbf\bfshape{10}{\magstep1}{OT1} |
2176 | 2174 | \setfont\deftt\ttshape{10}{\magstep1}{OT1TT} |
2177 | \setfont\defsl\slshape{10}{\magstep1}{OT1} | |
2175 | \setfont\defsl\slshape{10}{\magstep1}{OT1TT} | |
2178 | 2176 | \setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT} |
2179 | 2177 | \def\df{\let\ttfont=\deftt \let\bffont = \defbf |
2180 | 2178 | \let\ttslfont=\defttsl \let\slfont=\defsl \bf} |
2322 | 2320 | % A few fonts for @defun names and args. |
2323 | 2321 | \setfont\defbf\bfshape{10}{\magstephalf}{OT1} |
2324 | 2322 | \setfont\deftt\ttshape{10}{\magstephalf}{OT1TT} |
2325 | \setfont\defsl\slshape{10}{\magstephalf}{OT1} | |
2323 | \setfont\defsl\slshape{10}{\magstephalf}{OT1TT} | |
2326 | 2324 | \setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT} |
2327 | 2325 | \def\df{\let\ttfont=\deftt \let\bffont = \defbf |
2328 | 2326 | \let\slfont=\defsl \let\ttslfont=\defttsl \bf} |
2845 | 2843 | |
2846 | 2844 | % @t, explicit typewriter. |
2847 | 2845 | \def\t#1{% |
2848 | {\tt \plainfrenchspacing #1}% | |
2846 | {\tt \rawbackslash \plainfrenchspacing #1}% | |
2849 | 2847 | \null |
2850 | 2848 | } |
2851 | 2849 | |
2872 | 2870 | % Turn off hyphenation. |
2873 | 2871 | \nohyphenation |
2874 | 2872 | % |
2873 | \rawbackslash | |
2875 | 2874 | \plainfrenchspacing |
2876 | 2875 | #1% |
2877 | 2876 | }% |
3097 | 3096 | % Allow a ragged right output to aid breaking long URL's. Putting stretch in |
3098 | 3097 | % between characters of the URL doesn't look good. |
3099 | 3098 | \def\urefallowbreak{% |
3100 | \hskip 0pt plus 4 em\relax | |
3099 | \hskip 0pt plus 1fil\relax | |
3101 | 3100 | \allowbreak |
3102 | \hskip 0pt plus -4 em\relax | |
3101 | \hskip 0pt plus -1fil\relax | |
3103 | 3102 | } |
3104 | 3103 | |
3105 | 3104 | \urefbreakstyle after |
3112 | 3111 | % So now @email is just like @uref, unless we are pdf. |
3113 | 3112 | % |
3114 | 3113 | %\def\email#1{\angleleft{\tt #1}\angleright} |
3115 | \ifpdforxetex | |
3114 | \ifpdf | |
3116 | 3115 | \def\email#1{\doemail#1,,\finish} |
3117 | 3116 | \def\doemail#1,#2,#3\finish{\begingroup |
3118 | 3117 | \unsepspaces |
3122 | 3121 | \endlink |
3123 | 3122 | \endgroup} |
3124 | 3123 | \else |
3125 | \let\email=\uref | |
3124 | \ifx\XeTeXrevision\thisisundefined | |
3125 | \let\email=\uref | |
3126 | \else | |
3127 | \def\email#1{\doemail#1,,\finish} | |
3128 | \def\doemail#1,#2,#3\finish{\begingroup | |
3129 | \unsepspaces | |
3130 | \pdfurl{mailto:#1}% | |
3131 | \setbox0 = \hbox{\ignorespaces #2}% | |
3132 | \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi | |
3133 | \endlink | |
3134 | \endgroup} | |
3135 | \fi | |
3126 | 3136 | \fi |
3127 | 3137 | |
3128 | 3138 | % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), |
4656 | 4666 | } |
4657 | 4667 | } |
4658 | 4668 | |
4669 | % We have this subroutine so that we can handle at least some @value's | |
4670 | % properly in indexes (we call \makevalueexpandable in \indexdummies). | |
4671 | % The command has to be fully expandable (if the variable is set), since | |
4672 | % the result winds up in the index file. This means that if the | |
4673 | % variable's value contains other Texinfo commands, it's almost certain | |
4674 | % it will fail (although perhaps we could fix that with sufficient work | |
4675 | % to do a one-level expansion on the result, instead of complete). | |
4676 | % | |
4677 | % Unfortunately, this has the consequence that when _ is in the *value* | |
4678 | % of an @set, it does not print properly in the roman fonts (get the cmr | |
4679 | % dot accent at position 126 instead). No fix comes to mind, and it's | |
4680 | % been this way since 2003 or earlier, so just ignore it. | |
4681 | % | |
4659 | 4682 | \def\expandablevalue#1{% |
4660 | 4683 | \expandafter\ifx\csname SET#1\endcsname\relax |
4661 | 4684 | {[No value for ``#1'']}% |
4684 | 4707 | % if possible, otherwise sort late. |
4685 | 4708 | \def\indexnofontsvalue#1{% |
4686 | 4709 | \expandafter\ifx\csname SET#1\endcsname\relax |
4687 | ZZZZZZZ% | |
4710 | ZZZZZZZ | |
4688 | 4711 | \else |
4689 | 4712 | \csname SET#1\endcsname |
4690 | 4713 | \fi |
4834 | 4857 | \def\docodeindexxxx #1{\doind{\indexname}{\code{#1}}} |
4835 | 4858 | |
4836 | 4859 | |
4837 | % Used for the aux, toc and index files to prevent expansion of Texinfo | |
4838 | % commands. | |
4860 | % Used when writing an index entry out to an index file to prevent | |
4861 | % expansion of Texinfo commands that can appear in an index entry. | |
4862 | % | |
4863 | \def\indexdummies{% | |
4864 | \escapechar = `\\ % use backslash in output files. | |
4865 | \definedummyletter\@% | |
4866 | \definedummyletter\ % | |
4867 | % | |
4868 | % For texindex which always views { and } as separators. | |
4869 | \def\{{\lbracechar{}}% | |
4870 | \def\}{\rbracechar{}}% | |
4871 | % | |
4872 | % Do the redefinitions. | |
4873 | \definedummies | |
4874 | } | |
4875 | ||
4876 | % Used for the aux and toc files, where @ is the escape character. | |
4839 | 4877 | % |
4840 | 4878 | \def\atdummies{% |
4841 | 4879 | \definedummyletter\@% |
4865 | 4903 | \def\definedummyletter#1{\def#1{\string#1}}% |
4866 | 4904 | \let\definedummyaccent\definedummyletter |
4867 | 4905 | |
4868 | % Called from \atdummies to prevent the expansion of commands. | |
4906 | % Called from \indexdummies and \atdummies, to effectively prevent | |
4907 | % the expansion of commands. | |
4869 | 4908 | % |
4870 | 4909 | \def\definedummies{% |
4871 | 4910 | % |
4914 | 4953 | % Assorted special characters. |
4915 | 4954 | \definedummyword\atchar |
4916 | 4955 | \definedummyword\arrow |
4917 | \definedummyword\backslashchar | |
4918 | 4956 | \definedummyword\bullet |
4919 | 4957 | \definedummyword\comma |
4920 | 4958 | \definedummyword\copyright |
5031 | 5069 | \commondummyword\xref |
5032 | 5070 | } |
5033 | 5071 | |
5072 | % This does nothing, but for a time it was recommended to use | |
5073 | % \usebracesinindexestrue to be able to use braces in index entries. | |
5074 | ||
5034 | 5075 | \let\indexlbrace\relax |
5035 | 5076 | \let\indexrbrace\relax |
5036 | \let\indexatchar\relax | |
5037 | \let\indexbackslash\relax | |
5038 | 5077 | |
5039 | 5078 | {\catcode`\@=0 |
5040 | 5079 | \catcode`\\=13 |
5068 | 5107 | } |
5069 | 5108 | |
5070 | 5109 | \gdef\indexnonalnumreappear{% |
5110 | \useindexbackslash | |
5071 | 5111 | \let-\normaldash |
5072 | 5112 | \let<\normalless |
5113 | \def\@{@}% | |
5073 | 5114 | } |
5074 | 5115 | } |
5075 | 5116 | |
5180 | 5221 | |
5181 | 5222 | |
5182 | 5223 | |
5224 | \let\SETmarginindex=\relax % put index entries in margin (undocumented)? | |
5225 | ||
5183 | 5226 | % #1 is the index name, #2 is the entry text. |
5184 | 5227 | \def\doind#1#2{% |
5185 | 5228 | \iflinks |
5211 | 5254 | \fi} |
5212 | 5255 | \def\indexisfl{fl} |
5213 | 5256 | |
5257 | % Output \ as {\indexbackslash}, because \ is an escape character in | |
5258 | % the index files. | |
5259 | \let\indexbackslash=\relax | |
5260 | {\catcode`\@=0 \catcode`\\=\active | |
5261 | @gdef@useindexbackslash{@def\{{@indexbackslash}}} | |
5262 | } | |
5263 | ||
5214 | 5264 | % Definition for writing index entry sort key. |
5215 | 5265 | { |
5216 | 5266 | \catcode`\-=13 |
5222 | 5272 | \xdef\indexsortkey{#1}\endgroup} |
5223 | 5273 | } |
5224 | 5274 | |
5225 | \def\indexwriteseealso#1{ | |
5226 | \gdef\pagenumbertext{@seealso{#1}}% | |
5227 | } | |
5228 | \def\indexwriteseeentry#1{ | |
5229 | \gdef\pagenumbertext{@seeentry{#1}}% | |
5230 | } | |
5231 | ||
5232 | % The default definitions | |
5233 | \def\sortas#1{}% | |
5234 | \def\seealso#1{\i{\putwordSeeAlso}\ #1}% for sorted index file only | |
5235 | \def\putwordSeeAlso{See also} | |
5236 | \def\seeentry#1{\i{\putwordSee}\ #1}% for sorted index file only | |
5237 | ||
5238 | ||
5239 | 5275 | % Given index entry text like "aaa @subentry bbb @sortas{ZZZ}": |
5240 | 5276 | % * Set \bracedtext to "{aaa}{bbb}" |
5241 | 5277 | % * Set \fullindexsortkey to "aaa @subentry ZZZ" |
5242 | % * If @seealso occurs, set \pagenumbertext | |
5243 | 5278 | % |
5244 | 5279 | \def\splitindexentry#1{% |
5245 | 5280 | \gdef\fullindexsortkey{}% |
5246 | 5281 | \xdef\bracedtext{}% |
5247 | 5282 | \def\sep{}% |
5248 | \def\seealso##1{}% | |
5249 | \def\seeentry##1{}% | |
5250 | 5283 | \expandafter\doindexsegment#1\subentry\finish\subentry |
5251 | 5284 | } |
5252 | 5285 | |
5258 | 5291 | % |
5259 | 5292 | % Fully expand the segment, throwing away any @sortas directives, and |
5260 | 5293 | % trim spaces. |
5294 | \def\sortas##1{}% | |
5261 | 5295 | \edef\trimmed{\segment}% |
5262 | 5296 | \edef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}% |
5263 | 5297 | % |
5267 | 5301 | % font commands turned off. |
5268 | 5302 | \bgroup |
5269 | 5303 | \let\sortas\indexwritesortas |
5270 | \let\seealso\indexwriteseealso | |
5271 | \let\seeentry\indexwriteseeentry | |
5272 | 5304 | \indexnofonts |
5273 | 5305 | % The braces around the commands are recognized by texindex. |
5274 | \def\lbracechar{{\string\indexlbrace}}% | |
5275 | \def\rbracechar{{\string\indexrbrace}}% | |
5306 | \def\lbracechar{{\indexlbrace}}% | |
5307 | \def\rbracechar{{\indexrbrace}}% | |
5276 | 5308 | \let\{=\lbracechar |
5277 | 5309 | \let\}=\rbracechar |
5278 | \def\@{{\string\indexatchar}}% | |
5279 | \def\atchar##1{\@}% | |
5280 | \def\backslashchar{{\string\indexbackslash}}% | |
5281 | \uccode`\~=`\\ \uppercase{\let~\backslashchar}% | |
5282 | 5310 | % |
5283 | 5311 | \let\indexsortkey\empty |
5284 | \global\let\pagenumbertext\empty | |
5285 | 5312 | % Execute the segment and throw away the typeset output. This executes |
5286 | % any @sortas or @seealso commands in this segment. | |
5313 | % any @sortas commands in this segment. | |
5287 | 5314 | \setbox\dummybox = \hbox{\segment}% |
5288 | 5315 | \ifx\indexsortkey\empty{% |
5289 | 5316 | \indexnonalnumdisappear |
5304 | 5331 | \fi |
5305 | 5332 | } |
5306 | 5333 | \def\isfinish{\finish}% |
5307 | \newbox\dummybox % used above | |
5308 | 5334 | |
5309 | 5335 | \let\subentry\relax |
5310 | 5336 | |
5311 | % Use \ instead of @ in index files. To support old texi2dvi and texindex. | |
5312 | % This works without changing the escape character used in the toc or aux | |
5313 | % files because the index entries are fully expanded here, and \string uses | |
5314 | % the current value of \escapechar. | |
5315 | \def\escapeisbackslash{\escapechar=`\\} | |
5316 | ||
5317 | % Write the entry in \indextext to the index file. | |
5337 | % Write the entry in \toks0 to the index file. | |
5318 | 5338 | % |
5319 | 5339 | \def\doindwrite{% |
5320 | \maybemarginindex | |
5321 | % | |
5322 | \atdummies | |
5323 | % | |
5324 | \expandafter\ifx\csname SETtxiindexescapeisbackslash\endcsname\relax\else | |
5325 | \escapeisbackslash | |
5340 | % Put the index entry in the margin if desired. | |
5341 | \ifx\SETmarginindex\relax\else | |
5342 | \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% | |
5326 | 5343 | \fi |
5327 | 5344 | % |
5328 | % For texindex which always views { and } as separators. | |
5329 | \def\{{\lbracechar{}}% | |
5330 | \def\}{\rbracechar{}}% | |
5331 | \uccode`\~=`\\ \uppercase{\def~{\backslashchar{}}}% | |
5345 | % Remember, we are within a group. | |
5346 | \indexdummies % Must do this here, since \bf, etc expand at this stage | |
5347 | \useindexbackslash % \indexbackslash isn't defined now so it will be output | |
5348 | % as is; and it will print as backslash. | |
5332 | 5349 | % |
5333 | 5350 | % Split the entry into primary entry and any subentries, and get the index |
5334 | 5351 | % sort key. |
5342 | 5359 | % |
5343 | 5360 | \edef\temp{% |
5344 | 5361 | \write\writeto{% |
5345 | \string\entry{\fullindexsortkey}% | |
5346 | {\ifx\pagenumbertext\empty\noexpand\folio\else\pagenumbertext\fi}% | |
5347 | \bracedtext}% | |
5362 | \string\entry{\fullindexsortkey}{\noexpand\folio}\bracedtext}% | |
5348 | 5363 | }% |
5349 | 5364 | \temp |
5350 | 5365 | } |
5351 | ||
5352 | % Put the index entry in the margin if desired (undocumented). | |
5353 | \def\maybemarginindex{% | |
5354 | \ifx\SETmarginindex\relax\else | |
5355 | \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \relax\indextext}}% | |
5356 | \fi | |
5357 | } | |
5358 | \let\SETmarginindex=\relax | |
5359 | ||
5366 | \newbox\dummybox % used above | |
5360 | 5367 | |
5361 | 5368 | % Take care of unwanted page breaks/skips around a whatsit: |
5362 | 5369 | % |
5444 | 5451 | % \entry {topic}{pagelist} |
5445 | 5452 | % for a topic that is used without subtopics |
5446 | 5453 | % \primary {topic} |
5447 | % \entry {topic}{} | |
5448 | 5454 | % for the beginning of a topic that is used with subtopics |
5449 | 5455 | % \secondary {subtopic}{pagelist} |
5450 | 5456 | % for each subtopic. |
5451 | % \secondary {subtopic}{} | |
5452 | % for a subtopic with sub-subtopics | |
5453 | % \tertiary {subtopic}{subsubtopic}{pagelist} | |
5454 | % for each sub-subtopic. | |
5455 | 5457 | |
5456 | 5458 | % Define the user-accessible indexing commands |
5457 | 5459 | % @findex, @vindex, @kindex, @cindex. |
5476 | 5478 | \plainfrenchspacing |
5477 | 5479 | \everypar = {}% don't want the \kern\-parindent from indentation suppression. |
5478 | 5480 | % |
5481 | % See if the index file exists and is nonempty. | |
5482 | % Change catcode of @ here so that if the index file contains | |
5483 | % \initial {@} | |
5484 | % as its first line, TeX doesn't complain about mismatched braces | |
5485 | % (because it thinks @} is a control sequence). | |
5486 | \catcode`\@ = 12 | |
5479 | 5487 | % See comment in \requireopenindexfile. |
5480 | 5488 | \def\indexname{#1}\ifx\indexname\indexisfl\def\indexname{f1}\fi |
5481 | % | |
5482 | % See if the index file exists and is nonempty. | |
5483 | 5489 | \openin 1 \jobname.\indexname s |
5484 | 5490 | \ifeof 1 |
5485 | 5491 | % \enddoublecolumns gets confused if there is no text in the index, |
5489 | 5495 | \putwordIndexNonexistent |
5490 | 5496 | \typeout{No file \jobname.\indexname s.}% |
5491 | 5497 | \else |
5498 | \catcode`\\ = 0 | |
5499 | % | |
5492 | 5500 | % If the index file exists but is empty, then \openin leaves \ifeof |
5493 | 5501 | % false. We have to make TeX try to read something from the file, so |
5494 | 5502 | % it can discover if there is anything in it. |
5496 | 5504 | \ifeof 1 |
5497 | 5505 | \putwordIndexIsEmpty |
5498 | 5506 | \else |
5499 | \expandafter\printindexzz\thisline\relax\relax\finish% | |
5507 | % Index files are almost Texinfo source, but we use \ as the escape | |
5508 | % character. It would be better to use @, but that's too big a change | |
5509 | % to make right now. | |
5510 | \def\indexbackslash{\ttbackslash}% | |
5511 | \let\indexlbrace\{ % Likewise, set these sequences for braces | |
5512 | \let\indexrbrace\} % used in the sort key. | |
5513 | \begindoublecolumns | |
5514 | \let\dotheinsertentrybox\dotheinsertentryboxwithpenalty | |
5515 | % | |
5516 | % Read input from the index file line by line. | |
5517 | \loopdo | |
5518 | \ifeof1 \else | |
5519 | \read 1 to \nextline | |
5520 | \fi | |
5521 | % | |
5522 | \indexinputprocessing | |
5523 | \thisline | |
5524 | % | |
5525 | \ifeof1\else | |
5526 | \let\thisline\nextline | |
5527 | \repeat | |
5528 | %% | |
5529 | \enddoublecolumns | |
5500 | 5530 | \fi |
5501 | 5531 | \fi |
5502 | 5532 | \closein 1 |
5503 | 5533 | \endgroup} |
5504 | ||
5505 | % If the index file starts with a backslash, forgo reading the index | |
5506 | % file altogether. If somebody upgrades texinfo.tex they may still have | |
5507 | % old index files using \ as the escape character. Reading this would | |
5508 | % at best lead to typesetting garbage, at worst a TeX syntax error. | |
5509 | \def\printindexzz#1#2\finish{% | |
5510 | \expandafter\ifx\csname SETtxiindexescapeisbackslash\endcsname\relax | |
5511 | \uccode`\~=`\\ \uppercase{\if\noexpand~}\noexpand#1 | |
5512 | \expandafter\ifx\csname SETtxiskipindexfileswithbackslash\endcsname\relax | |
5513 | \errmessage{% | |
5514 | ERROR: A sorted index file in an obsolete format was skipped. | |
5515 | To fix this problem, please upgrade your version of 'texi2dvi' | |
5516 | or 'texi2pdf' to that at <https://ftp.gnu.org/gnu/texinfo>. | |
5517 | If you are using an old version of 'texindex' (part of the Texinfo | |
5518 | distribution), you may also need to upgrade to a newer version (at least 6.0). | |
5519 | You may be able to typeset the index if you run | |
5520 | 'texindex \jobname.\indexname' yourself. | |
5521 | You could also try setting the 'txiindexescapeisbackslash' flag by | |
5522 | running a command like | |
5523 | 'texi2dvi -t "@set txiindexescapeisbackslash" \jobname.texi'. If you do | |
5524 | this, Texinfo will try to use index files in the old format. | |
5525 | If you continue to have problems, deleting the index files and starting again | |
5526 | might help (with 'rm \jobname.?? \jobname.??s')% | |
5527 | }% | |
5528 | \else | |
5529 | (Skipped sorted index file in obsolete format) | |
5530 | \fi | |
5531 | \else | |
5532 | \begindoublecolumns | |
5533 | \input \jobname.\indexname s | |
5534 | \enddoublecolumns | |
5535 | \fi | |
5534 | \def\loopdo#1\repeat{\def\body{#1}\loopdoxxx} | |
5535 | \def\loopdoxxx{\let\next=\relax\body\let\next=\loopdoxxx\fi\next} | |
5536 | ||
5537 | \def\indexinputprocessing{% | |
5538 | \ifeof1 | |
5539 | \let\firsttoken\relax | |
5536 | 5540 | \else |
5537 | \message{trying to print index \indexname}% | |
5538 | \begindoublecolumns | |
5539 | \catcode`\\=0\relax | |
5540 | \catcode`\@=12\relax | |
5541 | \input \jobname.\indexname s | |
5542 | \enddoublecolumns | |
5541 | \edef\act{\gdef\noexpand\firsttoken{\getfirsttoken\nextline}}% | |
5542 | \act | |
5543 | 5543 | \fi |
5544 | 5544 | } |
5545 | \def\getfirsttoken#1{\expandafter\getfirsttokenx#1\endfirsttoken} | |
5546 | \long\def\getfirsttokenx#1#2\endfirsttoken{\noexpand#1} | |
5547 | ||
5545 | 5548 | |
5546 | 5549 | % These macros are used by the sorted index file itself. |
5547 | 5550 | % Change them to control the appearance of the index. |
5550 | 5553 | \catcode`\|=13 \catcode`\<=13 \catcode`\>=13 \catcode`\+=13 \catcode`\"=13 |
5551 | 5554 | \catcode`\$=3 |
5552 | 5555 | \gdef\initialglyphs{% |
5553 | % special control sequences used in the index sort key | |
5554 | \let\indexlbrace\{% | |
5555 | \let\indexrbrace\}% | |
5556 | \let\indexatchar\@% | |
5557 | \def\indexbackslash{\math{\backslash}}% | |
5558 | % | |
5559 | 5556 | % Some changes for non-alphabetic characters. Using the glyphs from the |
5560 | 5557 | % math fonts looks more consistent than the typewriter font used elsewhere |
5561 | 5558 | % for these characters. |
5562 | \uccode`\~=`\\ \uppercase{\def~{\math{\backslash}}} | |
5563 | % | |
5564 | % In case @\ is used for backslash | |
5565 | \uppercase{\let\\=~} | |
5559 | \def\indexbackslash{\math{\backslash}}% | |
5560 | \let\\=\indexbackslash | |
5561 | % | |
5566 | 5562 | % Can't get bold backslash so don't use bold forward slash |
5567 | 5563 | \catcode`\/=13 |
5568 | 5564 | \def/{{\secrmnotbold \normalslash}}% |
5621 | 5617 | % |
5622 | 5618 | \def\entry{% |
5623 | 5619 | \begingroup |
5620 | % | |
5621 | % For pdfTeX and XeTeX. | |
5622 | % The redefinition of \domark stops marks being added in \pdflink to | |
5623 | % preserve coloured links across page boundaries. Otherwise the marks | |
5624 | % would get in the way of \lastbox in \insertentrybox. | |
5625 | \let\domark\relax | |
5624 | 5626 | % |
5625 | 5627 | % Start a new paragraph if necessary, so our assignments below can't |
5626 | 5628 | % affect previous text. |
5654 | 5656 | \gdef\finishentry#1{% |
5655 | 5657 | \egroup % end box A |
5656 | 5658 | \dimen@ = \wd\boxA % Length of text of entry |
5657 | \global\setbox\boxA=\hbox\bgroup | |
5658 | \unhbox\boxA | |
5659 | % #1 is the page number. | |
5659 | \global\setbox\boxA=\hbox\bgroup\unhbox\boxA | |
5660 | % #1 is the page number. | |
5661 | % | |
5662 | % Get the width of the page numbers, and only use | |
5663 | % leaders if they are present. | |
5664 | \global\setbox\boxB = \hbox{#1}% | |
5665 | \ifdim\wd\boxB = 0pt | |
5666 | \null\nobreak\hfill\ % | |
5667 | \else | |
5660 | 5668 | % |
5661 | % Get the width of the page numbers, and only use | |
5662 | % leaders if they are present. | |
5663 | \global\setbox\boxB = \hbox{#1}% | |
5664 | \ifdim\wd\boxB = 0pt | |
5665 | \null\nobreak\hfill\ % | |
5669 | \null\nobreak\indexdotfill % Have leaders before the page number. | |
5670 | % | |
5671 | \ifpdf | |
5672 | \pdfgettoks#1.% | |
5673 | \hskip\skip\thinshrinkable\the\toksA | |
5666 | 5674 | \else |
5667 | % | |
5668 | \null\nobreak\indexdotfill % Have leaders before the page number. | |
5669 | % | |
5670 | \ifpdforxetex | |
5675 | \ifx\XeTeXrevision\thisisundefined | |
5676 | \hskip\skip\thinshrinkable #1% | |
5677 | \else | |
5671 | 5678 | \pdfgettoks#1.% |
5672 | 5679 | \hskip\skip\thinshrinkable\the\toksA |
5673 | \else | |
5674 | \hskip\skip\thinshrinkable #1% | |
5675 | 5680 | \fi |
5676 | 5681 | \fi |
5682 | \fi | |
5677 | 5683 | \egroup % end \boxA |
5678 | 5684 | \ifdim\wd\boxB = 0pt |
5679 | \noindent\unhbox\boxA\par | |
5680 | \nobreak | |
5681 | \else\bgroup | |
5685 | \global\setbox\entrybox=\vbox{\unhbox\boxA}% | |
5686 | \else | |
5687 | \global\setbox\entrybox=\vbox\bgroup | |
5682 | 5688 | % We want the text of the entries to be aligned to the left, and the |
5683 | 5689 | % page numbers to be aligned to the right. |
5684 | 5690 | % |
5744 | 5750 | \egroup % The \vbox |
5745 | 5751 | \fi |
5746 | 5752 | \endgroup |
5753 | \dotheinsertentrybox | |
5747 | 5754 | }} |
5748 | 5755 | |
5749 | 5756 | \newskip\thinshrinkable |
5750 | 5757 | \skip\thinshrinkable=.15em minus .15em |
5758 | ||
5759 | \newbox\entrybox | |
5760 | \def\insertentrybox{% | |
5761 | \ourunvbox\entrybox | |
5762 | } | |
5763 | ||
5764 | % default definition | |
5765 | \let\dotheinsertentrybox\insertentrybox | |
5766 | ||
5767 | % Use \lastbox to take apart vbox box by box, and add each sub-box | |
5768 | % to the current vertical list. | |
5769 | \def\ourunvbox#1{% | |
5770 | \bgroup % for local binding of \delayedbox | |
5771 | % Remove the last box from box #1 | |
5772 | \global\setbox#1=\vbox{% | |
5773 | \unvbox#1% | |
5774 | \unskip % remove any glue | |
5775 | \unpenalty | |
5776 | \global\setbox\interbox=\lastbox | |
5777 | }% | |
5778 | \setbox\delayedbox=\box\interbox | |
5779 | \ifdim\ht#1=0pt\else | |
5780 | \ourunvbox#1 % Repeat on what's left of the box | |
5781 | \nobreak | |
5782 | \fi | |
5783 | \box\delayedbox | |
5784 | \egroup | |
5785 | } | |
5786 | \newbox\delayedbox | |
5787 | \newbox\interbox | |
5788 | ||
5789 | % Used from \printindex. \firsttoken should be the first token | |
5790 | % after the \entry. If it's not another \entry, we are at the last | |
5791 | % line of a group of index entries, so insert a penalty to discourage | |
5792 | % widowed index entries. | |
5793 | \def\dotheinsertentryboxwithpenalty{% | |
5794 | \ifx\firsttoken\isentry | |
5795 | \else | |
5796 | \penalty 9000 | |
5797 | \fi | |
5798 | \insertentrybox | |
5799 | } | |
5800 | \def\isentry{\entry}% | |
5751 | 5801 | |
5752 | 5802 | % Like plain.tex's \dotfill, except uses up at least 1 em. |
5753 | 5803 | % The filll stretch here overpowers both the fil and fill stretch to push |
5758 | 5808 | |
5759 | 5809 | \def\primary #1{\line{#1\hfil}} |
5760 | 5810 | |
5761 | \def\secondary{\indententry{0.5cm}} | |
5762 | \def\tertiary{\indententry{1cm}} | |
5763 | ||
5764 | \def\indententry#1#2#3{% | |
5765 | \bgroup | |
5766 | \leftskip=#1 | |
5767 | \entry{#2}{#3}% | |
5768 | \egroup | |
5769 | } | |
5811 | \newskip\secondaryindent \secondaryindent=0.5cm | |
5812 | \def\secondary#1#2{{% | |
5813 | \parfillskip=0in | |
5814 | \parskip=0in | |
5815 | \hangindent=1in | |
5816 | \hangafter=1 | |
5817 | \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill | |
5818 | \ifpdf | |
5819 | \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. | |
5820 | \else | |
5821 | \ifx\XeTeXrevision\thisisundefined | |
5822 | #2 | |
5823 | \else | |
5824 | \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. | |
5825 | \fi | |
5826 | \fi | |
5827 | \par | |
5828 | }} | |
5770 | 5829 | |
5771 | 5830 | % Define two-column mode, which we use to typeset indexes. |
5772 | 5831 | % Adapted from the TeXbook, page 416, which is to say, |
5783 | 5842 | % Grab any single-column material above us. |
5784 | 5843 | \output = {% |
5785 | 5844 | \savetopmark |
5845 | % | |
5846 | % Here is a possibility not foreseen in manmac: if we accumulate a | |
5847 | % whole lot of material, we might end up calling this \output | |
5848 | % routine twice in a row (see the doublecol-lose test, which is | |
5849 | % essentially a couple of indexes with @setchapternewpage off). In | |
5850 | % that case we just ship out what is in \partialpage with the normal | |
5851 | % output routine. Generally, \partialpage will be empty when this | |
5852 | % runs and this will be a no-op. See the indexspread.tex test case. | |
5853 | \ifvoid\partialpage \else | |
5854 | \onepageout{\pagecontents\partialpage}% | |
5855 | \fi | |
5786 | 5856 | % |
5787 | 5857 | \global\setbox\partialpage = \vbox{% |
5788 | 5858 | % Unvbox the main output page. |
6063 | 6133 | |
6064 | 6134 | % @raisesections: treat @section as chapter, @subsection as section, etc. |
6065 | 6135 | \def\raisesections{\global\advance\secbase by -1} |
6136 | \let\up=\raisesections % original BFox name | |
6066 | 6137 | |
6067 | 6138 | % @lowersections: treat @chapter as section, @section as subsection, etc. |
6068 | 6139 | \def\lowersections{\global\advance\secbase by 1} |
6140 | \let\down=\lowersections % original BFox name | |
6069 | 6141 | |
6070 | 6142 | % we only have subsub. |
6071 | 6143 | \chardef\maxseclevel = 3 |
6717 | 6789 | % 1 and 2 (the page numbers aren't printed), and so are the first |
6718 | 6790 | % two pages of the document. Thus, we'd have two destinations named |
6719 | 6791 | % `1', and two named `2'. |
6720 | \ifpdforxetex | |
6792 | \ifpdf | |
6721 | 6793 | \global\pdfmakepagedesttrue |
6794 | \else | |
6795 | \ifx\XeTeXrevision\thisisundefined | |
6796 | \else | |
6797 | \global\pdfmakepagedesttrue | |
6798 | \fi | |
6722 | 6799 | \fi |
6723 | 6800 | } |
6724 | 6801 | |
7081 | 7158 | |
7082 | 7159 | % @cartouche ... @end cartouche: draw rectangle w/rounded corners around |
7083 | 7160 | % environment contents. |
7084 | ||
7161 | \font\circle=lcircle10 | |
7162 | \newdimen\circthick | |
7163 | \newdimen\cartouter\newdimen\cartinner | |
7164 | \newskip\normbskip\newskip\normpskip\newskip\normlskip | |
7165 | \circthick=\fontdimen8\circle | |
7085 | 7166 | % |
7086 | 7167 | \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth |
7087 | 7168 | \def\ctr{{\hskip 6pt\circle\char'010}} |
7096 | 7177 | % |
7097 | 7178 | \newskip\lskip\newskip\rskip |
7098 | 7179 | |
7099 | % only require the font if @cartouche is actually used | |
7100 | \def\cartouchefontdefs{% | |
7101 | \font\circle=lcircle10\relax | |
7102 | \circthick=\fontdimen8\circle | |
7103 | } | |
7104 | \newdimen\circthick | |
7105 | \newdimen\cartouter\newdimen\cartinner | |
7106 | \newskip\normbskip\newskip\normpskip\newskip\normlskip | |
7107 | ||
7108 | ||
7109 | 7180 | \envdef\cartouche{% |
7110 | \cartouchefontdefs | |
7111 | 7181 | \ifhmode\par\fi % can't be in the midst of a paragraph. |
7112 | 7182 | \startsavinginserts |
7113 | 7183 | \lskip=\leftskip \rskip=\rightskip |
7979 | 8049 | } |
7980 | 8050 | \fi |
7981 | 8051 | |
8052 | % alias because \c means cedilla in @tex or @math | |
8053 | \let\texinfoc=\c | |
8054 | ||
8055 | \newcount\savedcatcodeone | |
8056 | \newcount\savedcatcodetwo | |
8057 | ||
7982 | 8058 | % Used at the time of macro expansion. |
7983 | 8059 | % Argument is macro body with arguments substituted |
7984 | 8060 | \def\scanmacro#1{% |
7985 | 8061 | \newlinechar`\^^M |
7986 | 8062 | \def\xeatspaces{\eatspaces}% |
7987 | 8063 | % |
8064 | % Temporarily undo catcode changes of \printindex. Set catcode of @ to | |
8065 | % 0 so that @-commands in macro expansions aren't printed literally when | |
8066 | % formatting an index file, where \ is used as the escape character. | |
8067 | \savedcatcodeone=\catcode`\@ | |
8068 | \savedcatcodetwo=\catcode`\\ | |
8069 | \catcode`\@=0 | |
8070 | \catcode`\\=\active | |
8071 | % | |
7988 | 8072 | % Process the macro body under the current catcode regime. |
7989 | \scantokens{#1@comment}% | |
7990 | % | |
7991 | % The \comment is to remove the \newlinechar added by \scantokens, and | |
7992 | % can be noticed by \parsearg. Note \c isn't used because this means cedilla | |
7993 | % in math mode. | |
8073 | \scantokens{#1@texinfoc}% | |
8074 | % | |
8075 | \catcode`\@=\savedcatcodeone | |
8076 | \catcode`\\=\savedcatcodetwo | |
8077 | % | |
8078 | % The \texinfoc is to remove the \newlinechar added by \scantokens, and | |
8079 | % can be noticed by \parsearg. | |
8080 | % We avoid surrounding the call to \scantokens with \bgroup and \egroup | |
8081 | % to allow macros to open or close groups themselves. | |
7994 | 8082 | } |
7995 | 8083 | |
7996 | 8084 | % Used for copying and captions |
8091 | 8179 | \def\macroargctxt{% |
8092 | 8180 | \scanctxt |
8093 | 8181 | \catcode`\ =\active |
8094 | \catcode`\@=\other | |
8095 | 8182 | \catcode`\^^M=\other |
8096 | 8183 | \catcode`\\=\active |
8097 | 8184 | } |
8098 | 8185 | |
8099 | 8186 | \def\macrolineargctxt{% used for whole-line arguments without braces |
8100 | 8187 | \scanctxt |
8101 | \catcode`\@=\other | |
8102 | 8188 | \catcode`\{=\other |
8103 | 8189 | \catcode`\}=\other |
8104 | 8190 | } |
8662 | 8748 | % also remove a trailing comma, in case of something like this: |
8663 | 8749 | % @node Help-Cross, , , Cross-refs |
8664 | 8750 | \def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} |
8665 | \def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}\omittopnode} | |
8666 | ||
8667 | % Used so that the @top node doesn't have to be wrapped in an @ifnottex | |
8668 | % conditional. | |
8669 | % \doignore goes to more effort to skip nested conditionals but we don't need | |
8670 | % that here. | |
8671 | \def\omittopnode{% | |
8672 | \ifx\lastnode\wordTop | |
8673 | \expandafter\ignorenode\fi | |
8674 | } | |
8675 | \def\wordTop{Top} | |
8676 | ||
8677 | % Until the next @node or @bye command, divert output to a box that is not | |
8678 | % output. | |
8679 | \def\ignorenode{\setbox\dummybox\vbox\bgroup\def\node{\egroup\node}% | |
8680 | \ignorenodebye | |
8681 | } | |
8682 | ||
8683 | {\let\bye\relax | |
8684 | \gdef\ignorenodebye{\let\bye\ignorenodebyedef} | |
8685 | \gdef\ignorenodebyedef{\egroup(`Top' node ignored)\bye}} | |
8686 | % The redefinition of \bye here is because it is declared \outer | |
8687 | ||
8751 | \def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} | |
8752 | ||
8753 | \let\nwnode=\node | |
8688 | 8754 | \let\lastnode=\empty |
8689 | 8755 | |
8690 | 8756 | % Write a cross-reference definition for the current node. #1 is the |
9159 | 9225 | \catcode`\^^]=\other |
9160 | 9226 | \catcode`\^^^=\other |
9161 | 9227 | \catcode`\^^_=\other |
9228 | % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. | |
9229 | % in xref tags, i.e., node names. But since ^^e4 notation isn't | |
9230 | % supported in the main text, it doesn't seem desirable. Furthermore, | |
9231 | % that is not enough: for node names that actually contain a ^ | |
9232 | % character, we would end up writing a line like this: 'xrdef {'hat | |
9233 | % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first | |
9234 | % argument, and \hat is not an expandable control sequence. It could | |
9235 | % all be worked out, but why? Either we support ^^ or we don't. | |
9236 | % | |
9237 | % The other change necessary for this was to define \auxhat: | |
9238 | % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter | |
9239 | % and then to call \auxhat in \setq. | |
9240 | % | |
9162 | 9241 | \catcode`\^=\other |
9163 | 9242 | % |
9164 | 9243 | % Special characters. Should be turned off anyway, but... |
9176 | 9255 | \catcode`\%=\other |
9177 | 9256 | \catcode`+=\other % avoid \+ for paranoia even though we've turned it off |
9178 | 9257 | % |
9179 | \catcode`\\=\active | |
9258 | % This is to support \ in node names and titles, since the \ | |
9259 | % characters end up in a \csname. It's easier than | |
9260 | % leaving it active and making its active definition an actual \ | |
9261 | % character. What I don't understand is why it works in the *value* | |
9262 | % of the xrdef. Seems like it should be a catcode12 \, and that | |
9263 | % should not typeset properly. But it works, so I'm moving on for | |
9264 | % now. --karl, 15jan04. | |
9265 | \catcode`\\=\other | |
9180 | 9266 | % |
9181 | 9267 | % @ is our escape character in .aux files, and we need braces. |
9182 | 9268 | \catcode`\{=1 |
11447 | 11533 | % \backslashcurfont outputs one backslash character in current font, |
11448 | 11534 | % as in \char`\\. |
11449 | 11535 | \global\chardef\backslashcurfont=`\\ |
11450 | ||
11451 | % \realbackslash is an actual character `\' with catcode other. | |
11452 | {\catcode`\\=\other @gdef@realbackslash{\}} | |
11536 | \global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work | |
11537 | ||
11538 | % \realbackslash is an actual character `\' with catcode other, and | |
11539 | % \doublebackslash is two of them (for the pdf outlines). | |
11540 | {\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} | |
11453 | 11541 | |
11454 | 11542 | % In Texinfo, backslash is an active character; it prints the backslash |
11455 | 11543 | % in fixed width font. |
11467 | 11555 | @def@ttbackslash{{@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}} |
11468 | 11556 | @let@backslashchar = @ttbackslash % @backslashchar{} is for user documents. |
11469 | 11557 | |
11558 | % \rawbackslash defines an active \ to do \backslashcurfont. | |
11470 | 11559 | % \otherbackslash defines an active \ to be a literal `\' character with |
11471 | % catcode other. | |
11560 | % catcode other. We switch back and forth between these. | |
11561 | @gdef@rawbackslash{@let\=@backslashcurfont} | |
11472 | 11562 | @gdef@otherbackslash{@let\=@realbackslash} |
11473 | 11563 | |
11474 | 11564 | % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of |
11540 | 11630 | @ifx\@eatinput @let\ = @ttbackslash @fi |
11541 | 11631 | @catcode13=5 % regular end of line |
11542 | 11632 | @enableemergencynewline |
11543 | @let@c=@comment | |
11633 | @let@c=@texinfoc | |
11544 | 11634 | @let@parsearg@originalparsearg |
11545 | 11635 | % Also turn back on active characters that might appear in the input |
11546 | 11636 | % file name, in case not using a pre-dumped format. |
24887 | 24887 | test "x$srcdir" = x. || msg_compiling="$msg_compiling |
24888 | 24888 | from sources in $kpse_src" |
24889 | 24889 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: |
24890 | ** Configuration summary for $PACKAGE_STRING (2020/dev$with_banner_add): | |
24890 | ** Configuration summary for $PACKAGE_STRING (2019$with_banner_add): | |
24891 | 24891 | |
24892 | 24892 | $msg_compiling" >&5 |
24893 | 24893 | $as_echo " |
24894 | ** Configuration summary for $PACKAGE_STRING (2020/dev$with_banner_add): | |
24894 | ** Configuration summary for $PACKAGE_STRING (2019$with_banner_add): | |
24895 | 24895 | |
24896 | 24896 | $msg_compiling" >&6; } |
24897 | 24897 | case $kpse_src$kpse_bld in |
11 | 11 | cairo 1.16.0 - checked 20oct18 |
12 | 12 | http://cairographics.org/releases/ |
13 | 13 | |
14 | freetype2 2.10.0 - checked 03may19 | |
14 | freetype2 2.9.1 - checked 04may18 | |
15 | 15 | http://savannah.nongnu.org/download/freetype/ |
16 | 16 | |
17 | 17 | gd 2.2.5 - checked 30aug17 |
24 | 24 | http://sourceforge.net/projects/silgraphite/files/graphite2/ |
25 | 25 | (requires C++11) |
26 | 26 | |
27 | harfbuzz 2.4.0 - checked 03may19 | |
27 | harfbuzz 2.3.1 - checked 31jan19 | |
28 | 28 | http://www.freedesktop.org/software/harfbuzz/release/ |
29 | 29 | |
30 | 30 | icu 63.1 - checked 8jan19 |
33 | 33 | libpaper 1.1.24+nmu2 - checked 24oct13 |
34 | 34 | ftp://ftp.de.debian.org/debian/pool/main/libp/libpaper/ |
35 | 35 | |
36 | libpng 1.6.37 - checked 03may19 | |
36 | libpng 1.6.36 - checked 02dec18 | |
37 | 37 | https://sourceforge.net/projects/libpng/files/ - used by many |
38 | 38 | |
39 | 39 | lua 5.2.4 - checked 11mar15 |
48 | 48 | mpfr 4.0.2 - checked 1jan19 |
49 | 49 | http://ftp.gnu.org/gnu/mpfr/ |
50 | 50 | |
51 | pixman 0.38.4 - checked 03may19 | |
51 | pixman 0.38.0 - checked 13feb19 | |
52 | 52 | http://cairographics.org/releases/ |
53 | 53 | |
54 | 54 | poppler 0.68.0 - checked 20aug18 |
55 | 55 | http://poppler.freedesktop.org/ - used by xetex |
56 | 56 | (requires C++11) |
57 | 57 | |
58 | teckit 2.5.9 - checked 03may19 | |
59 | https://github.com/silnrsi/teckit/archive/2.5.9.tar.gz | |
58 | teckit 2.5.8 - checked 24jul18 | |
59 | https://github.com/silnrsi/teckit/archive/2.5.8.tar.gz | |
60 | 60 | |
61 | xpdf 4.01.01 - checked 03may19 | |
61 | xpdf 4.01 - checked 25feb19 | |
62 | 62 | http://www.xpdfreader.com/download.html |
63 | 63 | with modifications for pdftex |
64 | 64 |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for TeX Live libs 2020/dev. | |
2 | # Generated by GNU Autoconf 2.69 for TeX Live libs 2019. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-k@tug.org>. |
5 | 5 | # |
578 | 578 | # Identity of this package. |
579 | 579 | PACKAGE_NAME='TeX Live libs' |
580 | 580 | PACKAGE_TARNAME='tex-live-libs' |
581 | PACKAGE_VERSION='2020/dev' | |
582 | PACKAGE_STRING='TeX Live libs 2020/dev' | |
581 | PACKAGE_VERSION='2019' | |
582 | PACKAGE_STRING='TeX Live libs 2019' | |
583 | 583 | PACKAGE_BUGREPORT='tex-k@tug.org' |
584 | 584 | PACKAGE_URL='' |
585 | 585 | |
1392 | 1392 | # Omit some internal or obsolete options to make the list less imposing. |
1393 | 1393 | # This message is too long to be a string in the A/UX 3.1 sh. |
1394 | 1394 | cat <<_ACEOF |
1395 | \`configure' configures TeX Live libs 2020/dev to adapt to many kinds of systems. | |
1395 | \`configure' configures TeX Live libs 2019 to adapt to many kinds of systems. | |
1396 | 1396 | |
1397 | 1397 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1398 | 1398 | |
1462 | 1462 | |
1463 | 1463 | if test -n "$ac_init_help"; then |
1464 | 1464 | case $ac_init_help in |
1465 | short | recursive ) echo "Configuration of TeX Live libs 2020/dev:";; | |
1465 | short | recursive ) echo "Configuration of TeX Live libs 2019:";; | |
1466 | 1466 | esac |
1467 | 1467 | cat <<\_ACEOF |
1468 | 1468 | |
1748 | 1748 | test -n "$ac_init_help" && exit $ac_status |
1749 | 1749 | if $ac_init_version; then |
1750 | 1750 | cat <<\_ACEOF |
1751 | TeX Live libs configure 2020/dev | |
1751 | TeX Live libs configure 2019 | |
1752 | 1752 | generated by GNU Autoconf 2.69 |
1753 | 1753 | |
1754 | 1754 | Copyright (C) 2012 Free Software Foundation, Inc. |
1849 | 1849 | This file contains any messages produced by compilers while |
1850 | 1850 | running configure, to aid debugging if configure makes a mistake. |
1851 | 1851 | |
1852 | It was created by TeX Live libs $as_me 2020/dev, which was | |
1852 | It was created by TeX Live libs $as_me 2019, which was | |
1853 | 1853 | generated by GNU Autoconf 2.69. Invocation command line was |
1854 | 1854 | |
1855 | 1855 | $ $0 $@ |
6058 | 6058 | |
6059 | 6059 | # Define the identity of the package. |
6060 | 6060 | PACKAGE='tex-live-libs' |
6061 | VERSION='2020/dev' | |
6061 | VERSION='2019' | |
6062 | 6062 | |
6063 | 6063 | |
6064 | 6064 | cat >>confdefs.h <<_ACEOF |
7043 | 7043 | # report actual input values of CONFIG_FILES etc. instead of their |
7044 | 7044 | # values after options handling. |
7045 | 7045 | ac_log=" |
7046 | This file was extended by TeX Live libs $as_me 2020/dev, which was | |
7046 | This file was extended by TeX Live libs $as_me 2019, which was | |
7047 | 7047 | generated by GNU Autoconf 2.69. Invocation command line was |
7048 | 7048 | |
7049 | 7049 | CONFIG_FILES = $CONFIG_FILES |
7100 | 7100 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
7101 | 7101 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
7102 | 7102 | ac_cs_version="\\ |
7103 | TeX Live libs config.status 2020/dev | |
7103 | TeX Live libs config.status 2019 | |
7104 | 7104 | configured by $0, generated by GNU Autoconf 2.69, |
7105 | 7105 | with options \\"\$ac_cs_config\\" |
7106 | 7106 |
0 | 2019-05-03 Akira Kakuto <kakuto@w32tex.org> | |
1 | ||
2 | * Import xpdf-4.01.01. | |
3 | * version.ac: Adjust. | |
4 | ||
5 | 0 | 2019-02-25 Akira Kakuto <kakuto@w32tex.org> |
6 | 1 | |
7 | 2 | * Import xpdf-4.01. |
0 | 2019-05-03 Akira Kakuto <kakuto@w32tex.org> | |
1 | ||
2 | * patch-bunched: Adjust. | |
3 | ||
4 | 0 | 2019-02-25 Akira Kakuto <kakuto@w32tex.org> |
5 | 1 | |
6 | 2 | * patch-bunched: Adjust. |
0 | Changes applied to the xpdf-4.01.01/ tree as obtained from: | |
0 | Changes applied to the xpdf-4.01/ tree as obtained from: | |
1 | 1 | http://www.xpdfreader.com/download.html |
2 | 2 | |
3 | 3 | Removed: |
0 | diff -ur xpdf-4.01.01/goo/gfile.cc xpdf-src/goo/gfile.cc | |
1 | --- xpdf-4.01.01/goo/gfile.cc Fri Mar 15 06:01:02 2019 | |
0 | diff -ur xpdf-4.01/goo/gfile.cc xpdf-src/goo/gfile.cc | |
1 | --- xpdf-4.01/goo/gfile.cc Tue Feb 19 03:24:19 2019 | |
2 | 2 | +++ xpdf-src/goo/gfile.cc Mon Feb 25 11:09:32 2019 |
3 | 3 | @@ -7,6 +7,9 @@ |
4 | 4 | // Copyright 1996-2003 Glyph & Cog, LLC |
73 | 73 | #endif |
74 | 74 | } |
75 | 75 | +#endif /* !PDF_PARSER_ONLY */ |
76 | diff -ur xpdf-4.01.01/goo/gfile.h xpdf-src/goo/gfile.h | |
77 | --- xpdf-4.01.01/goo/gfile.h Fri Mar 15 06:01:02 2019 | |
76 | diff -ur xpdf-4.01/goo/gfile.h xpdf-src/goo/gfile.h | |
77 | --- xpdf-4.01/goo/gfile.h Tue Feb 19 03:24:19 2019 | |
78 | 78 | +++ xpdf-src/goo/gfile.h Mon Feb 25 11:07:26 2019 |
79 | 79 | @@ -114,6 +114,8 @@ |
80 | 80 | |
85 | 85 | +#endif /* !PDF_PARSER_ONLY */ |
86 | 86 | |
87 | 87 | #endif |
88 | diff -ur xpdf-4.01.01/xpdf/GlobalParams.cc xpdf-src/xpdf/GlobalParams.cc | |
89 | --- xpdf-4.01.01/xpdf/GlobalParams.cc Fri Mar 15 06:01:02 2019 | |
88 | diff -ur xpdf-4.01/xpdf/GlobalParams.cc xpdf-src/xpdf/GlobalParams.cc | |
89 | --- xpdf-4.01/xpdf/GlobalParams.cc Tue Feb 19 03:24:19 2019 | |
90 | 90 | +++ xpdf-src/xpdf/GlobalParams.cc Mon Feb 25 08:01:11 2019 |
91 | 91 | @@ -5,6 +5,9 @@ |
92 | 92 | // Copyright 2001-2003 Glyph & Cog, LLC |
141 | 141 | } |
142 | 142 | } |
143 | 143 | } |
144 | diff -ur xpdf-4.01.01/xpdf/GlobalParams.h xpdf-src/xpdf/GlobalParams.h | |
145 | --- xpdf-4.01.01/xpdf/GlobalParams.h Fri Mar 15 06:01:02 2019 | |
144 | diff -ur xpdf-4.01/xpdf/GlobalParams.h xpdf-src/xpdf/GlobalParams.h | |
145 | --- xpdf-4.01/xpdf/GlobalParams.h Tue Feb 19 03:24:19 2019 | |
146 | 146 | +++ xpdf-src/xpdf/GlobalParams.h Mon Feb 25 08:02:36 2019 |
147 | 147 | @@ -5,6 +5,9 @@ |
148 | 148 | // Copyright 2001-2003 Glyph & Cog, LLC |
163 | 163 | |
164 | 164 | ~GlobalParams(); |
165 | 165 | |
166 | diff -ur xpdf-4.01.01/xpdf/PDFDoc.cc xpdf-src/xpdf/PDFDoc.cc | |
167 | --- xpdf-4.01.01/xpdf/PDFDoc.cc Fri Mar 15 06:01:02 2019 | |
168 | +++ xpdf-src/xpdf/PDFDoc.cc Sun Mar 17 08:59:43 2019 | |
166 | diff -ur xpdf-4.01/xpdf/PDFDoc.cc xpdf-src/xpdf/PDFDoc.cc | |
167 | --- xpdf-4.01/xpdf/PDFDoc.cc Tue Feb 19 03:24:19 2019 | |
168 | +++ xpdf-src/xpdf/PDFDoc.cc Mon Feb 25 08:16:35 2019 | |
169 | 169 | @@ -147,20 +147,25 @@ |
170 | 170 | |
171 | 171 | PDFDoc::PDFDoc(char *fileNameA, GString *ownerPassword, |
205 | 205 | #elif defined(VMS) |
206 | 206 | file = fopen(fileName->getCString(), "rb", "ctx=stm"); |
207 | 207 | #else |
208 | @@ -572,6 +581,7 @@ | |
208 | @@ -571,6 +580,7 @@ | |
209 | 209 | GBool ret; |
210 | 210 | |
211 | 211 | // NB: _wfopen is only available in NT |
213 | 213 | version.dwOSVersionInfoSize = sizeof(version); |
214 | 214 | GetVersionEx(&version); |
215 | 215 | if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { |
216 | @@ -581,12 +591,15 @@ | |
216 | @@ -580,12 +590,15 @@ | |
217 | 217 | path2w[i] = 0; |
218 | 218 | f = _wfopen(path2w, L"wb"); |
219 | 219 | } else { |
229 | 229 | if (!f) { |
230 | 230 | return gFalse; |
231 | 231 | } |
232 | diff -ur xpdf-4.01.01/xpdf/Page.cc xpdf-src/xpdf/Page.cc | |
233 | --- xpdf-4.01.01/xpdf/Page.cc Fri Mar 15 06:01:02 2019 | |
232 | diff -ur xpdf-4.01/xpdf/Page.cc xpdf-src/xpdf/Page.cc | |
233 | --- xpdf-4.01/xpdf/Page.cc Tue Feb 19 03:24:19 2019 | |
234 | 234 | +++ xpdf-src/xpdf/Page.cc Mon Feb 25 08:19:00 2019 |
235 | 235 | @@ -480,9 +480,9 @@ |
236 | 236 | delete links; |
250 | 250 | -} |
251 | 251 | #endif |
252 | 252 | +} |
253 | diff -ur xpdf-4.01.01/xpdf/XFAForm.cc xpdf-src/xpdf/XFAForm.cc | |
254 | --- xpdf-4.01.01/xpdf/XFAForm.cc Fri Mar 15 06:01:02 2019 | |
253 | diff -ur xpdf-4.01/xpdf/XFAForm.cc xpdf-src/xpdf/XFAForm.cc | |
254 | --- xpdf-4.01/xpdf/XFAForm.cc Tue Feb 19 03:24:19 2019 | |
255 | 255 | +++ xpdf-src/xpdf/XFAForm.cc Mon Feb 25 08:20:00 2019 |
256 | 256 | @@ -28,8 +28,10 @@ |
257 | 257 | #include "XFAForm.h" |
266 | 266 | #endif |
267 | 267 | |
268 | 268 | //------------------------------------------------------------------------ |
269 | diff -ur xpdf-4.01.01/xpdf/config.h xpdf-src/xpdf/config.h | |
270 | --- xpdf-4.01.01/xpdf/config.h Fri Mar 15 06:01:02 2019 | |
271 | +++ xpdf-src/xpdf/config.h Sun Mar 17 16:09:03 2019 | |
269 | diff -ur xpdf-4.01/xpdf/config.h xpdf-src/xpdf/config.h | |
270 | --- xpdf-4.01/xpdf/config.h Tue Feb 19 03:24:19 2019 | |
271 | +++ xpdf-src/xpdf/config.h Mon Feb 25 08:21:02 2019 | |
272 | 272 | @@ -78,11 +78,6 @@ |
273 | 273 | // popen |
274 | 274 | //------------------------------------------------------------------------ |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for xpdf (TeX Live) 4.01.01. | |
2 | # Generated by GNU Autoconf 2.69 for xpdf (TeX Live) 4.01. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-k@tug.org>. |
5 | 5 | # |
579 | 579 | # Identity of this package. |
580 | 580 | PACKAGE_NAME='xpdf (TeX Live)' |
581 | 581 | PACKAGE_TARNAME='xpdf--tex-live-' |
582 | PACKAGE_VERSION='4.01.01' | |
583 | PACKAGE_STRING='xpdf (TeX Live) 4.01.01' | |
582 | PACKAGE_VERSION='4.01' | |
583 | PACKAGE_STRING='xpdf (TeX Live) 4.01' | |
584 | 584 | PACKAGE_BUGREPORT='tex-k@tug.org' |
585 | 585 | PACKAGE_URL='' |
586 | 586 | |
1289 | 1289 | # Omit some internal or obsolete options to make the list less imposing. |
1290 | 1290 | # This message is too long to be a string in the A/UX 3.1 sh. |
1291 | 1291 | cat <<_ACEOF |
1292 | \`configure' configures xpdf (TeX Live) 4.01.01 to adapt to many kinds of systems. | |
1292 | \`configure' configures xpdf (TeX Live) 4.01 to adapt to many kinds of systems. | |
1293 | 1293 | |
1294 | 1294 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1295 | 1295 | |
1355 | 1355 | |
1356 | 1356 | if test -n "$ac_init_help"; then |
1357 | 1357 | case $ac_init_help in |
1358 | short | recursive ) echo "Configuration of xpdf (TeX Live) 4.01.01:";; | |
1358 | short | recursive ) echo "Configuration of xpdf (TeX Live) 4.01:";; | |
1359 | 1359 | esac |
1360 | 1360 | cat <<\_ACEOF |
1361 | 1361 | |
1459 | 1459 | test -n "$ac_init_help" && exit $ac_status |
1460 | 1460 | if $ac_init_version; then |
1461 | 1461 | cat <<\_ACEOF |
1462 | xpdf (TeX Live) configure 4.01.01 | |
1462 | xpdf (TeX Live) configure 4.01 | |
1463 | 1463 | generated by GNU Autoconf 2.69 |
1464 | 1464 | |
1465 | 1465 | Copyright (C) 2012 Free Software Foundation, Inc. |
1866 | 1866 | This file contains any messages produced by compilers while |
1867 | 1867 | running configure, to aid debugging if configure makes a mistake. |
1868 | 1868 | |
1869 | It was created by xpdf (TeX Live) $as_me 4.01.01, which was | |
1869 | It was created by xpdf (TeX Live) $as_me 4.01, which was | |
1870 | 1870 | generated by GNU Autoconf 2.69. Invocation command line was |
1871 | 1871 | |
1872 | 1872 | $ $0 $@ |
3790 | 3790 | |
3791 | 3791 | # Define the identity of the package. |
3792 | 3792 | PACKAGE='xpdf--tex-live-' |
3793 | VERSION='4.01.01' | |
3793 | VERSION='4.01' | |
3794 | 3794 | |
3795 | 3795 | |
3796 | 3796 | # Some tools Automake needs. |
6703 | 6703 | # report actual input values of CONFIG_FILES etc. instead of their |
6704 | 6704 | # values after options handling. |
6705 | 6705 | ac_log=" |
6706 | This file was extended by xpdf (TeX Live) $as_me 4.01.01, which was | |
6706 | This file was extended by xpdf (TeX Live) $as_me 4.01, which was | |
6707 | 6707 | generated by GNU Autoconf 2.69. Invocation command line was |
6708 | 6708 | |
6709 | 6709 | CONFIG_FILES = $CONFIG_FILES |
6773 | 6773 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
6774 | 6774 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
6775 | 6775 | ac_cs_version="\\ |
6776 | xpdf (TeX Live) config.status 4.01.01 | |
6776 | xpdf (TeX Live) config.status 4.01 | |
6777 | 6777 | configured by $0, generated by GNU Autoconf 2.69, |
6778 | 6778 | with options \\"\$ac_cs_config\\" |
6779 | 6779 |
7 | 7 | dnl -------------------------------------------------------- |
8 | 8 | dnl |
9 | 9 | dnl m4-include this file to define the current xpdf version |
10 | m4_define([xpdf_version], [4.01.01]) | |
10 | m4_define([xpdf_version], [4.01]) |
2538 | 2538 | [Thanks to r4xis for the bug report.] |
2539 | 2539 | Check for invalid quant table indexes in the DCT decoder. [Thanks to |
2540 | 2540 | r4xis for the bug report.] |
2541 | ||
2542 | 4.01.01 (2019-mar-14) | |
2543 | --------------------- | |
2544 | The PDFDoc(BaseStream) initializer wasn't working correctly. | |
2545 | Fixed a missing array bounds check in PSOutputDev. [Thanks to | |
2546 | Loginsoft for the bug report.] | |
2547 | If the "U" string used for RC4 decryption is short, Adobe apparently | |
2548 | zero-pads it, so Xpdf now does the same. | |
2549 | Pdffonts now checks more carefully for loops between objects. | |
2550 | Fixed a problem parsing large real numbers. [Thanks to Loginsoft for | |
2551 | the bug report.] |
0 | 0 | Xpdf |
1 | 1 | ==== |
2 | 2 | |
3 | version 4.01.01 | |
4 | 2019-mar-14 | |
3 | version 4.01 | |
4 | 2019-feb-18 | |
5 | 5 | |
6 | 6 | The Xpdf software and documentation are |
7 | 7 | copyright 1996-2019 Glyph & Cog, LLC. |
0 | 0 | Xpdf |
1 | 1 | ==== |
2 | 2 | |
3 | version 4.01.01 | |
4 | 2019-mar-14 | |
3 | version 4.01 | |
4 | 2019-feb-18 | |
5 | 5 | |
6 | 6 | The Xpdf software and documentation are |
7 | 7 | copyright 1996-2019 Glyph & Cog, LLC. |
4566 | 4566 | SplashCoord xMin, yMin, xMax, yMax, t; |
4567 | 4567 | SplashCoord mi0, mi1, mi2, mi3, mi4, mi5, det; |
4568 | 4568 | SplashCoord ix, iy, sx, sy, pix0, pix1; |
4569 | SplashBitmapRowSize rowSize; | |
4570 | int xMinI, yMinI, xMaxI, yMaxI, x, y, x0, y0, x1, y1, tt, i; | |
4569 | int rowSize, xMinI, yMinI, xMaxI, yMaxI, x, y, x0, y0, x1, y1, tt, i; | |
4571 | 4570 | |
4572 | 4571 | // compute the bbox of the target quadrilateral |
4573 | 4572 | xMin = xMax = mat[4]; |
4653 | 4652 | } else { |
4654 | 4653 | rowSize = srcWidth * nComps; |
4655 | 4654 | } |
4656 | unscaledImage = (SplashColorPtr)gmallocn64(srcHeight, rowSize); | |
4655 | unscaledImage = (SplashColorPtr)gmallocn(srcHeight, rowSize); | |
4657 | 4656 | if (srcAlpha) { |
4658 | 4657 | unscaledAlpha = (Guchar *)gmallocn(srcHeight, srcWidth); |
4659 | 4658 | for (y = 0, p = unscaledImage, alphaPtr = unscaledAlpha; |
4663 | 4662 | } |
4664 | 4663 | } else { |
4665 | 4664 | unscaledAlpha = NULL; |
4666 | for (y = 0, p = unscaledImage; y < srcHeight; ++y, p += rowSize) { | |
4665 | for (y = 0, p = unscaledImage; y < srcHeight; ++y, p += srcWidth * nComps) { | |
4667 | 4666 | (*src)(srcData, p, NULL); |
4668 | 4667 | } |
4669 | 4668 | } |
4698 | 4697 | if (y1 >= srcHeight) { |
4699 | 4698 | y1 = srcHeight - 1; |
4700 | 4699 | } |
4701 | q00 = &unscaledImage[y0 * rowSize + (SplashBitmapRowSize)x0 * nComps]; | |
4702 | q01 = &unscaledImage[y0 * rowSize + (SplashBitmapRowSize)x1 * nComps]; | |
4703 | q10 = &unscaledImage[y1 * rowSize + (SplashBitmapRowSize)x0 * nComps]; | |
4704 | q11 = &unscaledImage[y1 * rowSize + (SplashBitmapRowSize)x1 * nComps]; | |
4700 | q00 = &unscaledImage[(y0 * srcWidth + x0) * nComps]; | |
4701 | q01 = &unscaledImage[(y0 * srcWidth + x1) * nComps]; | |
4702 | q10 = &unscaledImage[(y1 * srcWidth + x0) * nComps]; | |
4703 | q11 = &unscaledImage[(y1 * srcWidth + x1) * nComps]; | |
4705 | 4704 | for (i = 0; i < nComps; ++i) { |
4706 | 4705 | pix0 = ((SplashCoord)1 - sx) * (int)*q00++ + sx * (int)*q01++; |
4707 | 4706 | pix1 = ((SplashCoord)1 - sx) * (int)*q10++ + sx * (int)*q11++; |
4730 | 4729 | x0 = splashFloor(ix); |
4731 | 4730 | y0 = splashFloor(iy); |
4732 | 4731 | if (x0 >= 0 && x0 < srcWidth && y0 >= 0 && y0 < srcHeight) { |
4733 | q = &unscaledImage[y0 * rowSize + (SplashBitmapRowSize)x0 * nComps]; | |
4732 | q = &unscaledImage[(y0 * srcWidth + x0) * nComps]; | |
4734 | 4733 | for (i = 0; i < nComps; ++i) { |
4735 | 4734 | *p++ = *q++; |
4736 | 4735 | } |
1541 | 1541 | fontSize = atof(tok->getCString()); |
1542 | 1542 | } else { |
1543 | 1543 | error(errSyntaxError, -1, "Missing 'Tf' operator in field's DA string"); |
1544 | fontSize = 10; | |
1545 | if (!daToks) { | |
1546 | daToks = new GList(); | |
1547 | } | |
1548 | daToks->append(new GString("/xpdf_default_font")); | |
1549 | daToks->append(new GString("10")); | |
1550 | daToks->append(new GString("Tf")); | |
1551 | 1544 | } |
1552 | 1545 | |
1553 | 1546 | // setup |
1609 | 1602 | // starting y coordinate |
1610 | 1603 | // (note: each line of text starts with a Td operator that moves |
1611 | 1604 | // down a line) |
1612 | if (dy > fontSize + 6) { | |
1613 | y = dy - 3; | |
1614 | } else { | |
1615 | y = 0.5 * dy - 0.4 * fontSize + fontSize; | |
1616 | } | |
1605 | y = dy - 3; | |
1617 | 1606 | |
1618 | 1607 | // set the font matrix |
1619 | 1608 | if (tmPos >= 0) { |
178 | 178 | if (isdigit(c)) { |
179 | 179 | getChar(); |
180 | 180 | xi = xi * 10 + (c - '0'); |
181 | if (xf < 1e20) { | |
182 | xf = xf * 10 + (c - '0'); | |
183 | } | |
181 | xf = xf * 10 + (c - '0'); | |
184 | 182 | } else if (c == '.') { |
185 | 183 | getChar(); |
186 | 184 | goto doReal; |
689 | 689 | void PDFCore::scrollToBottomRight() { |
690 | 690 | scrollTo(tileMap->getPageRightX(tileMap->getLastPage()), |
691 | 691 | tileMap->getPageBottomY(tileMap->getLastPage())); |
692 | } | |
693 | ||
694 | void PDFCore::scrollToCentered(int page, double x, double y) { | |
695 | int wx, wy, sx, sy; | |
696 | ||
697 | startUpdate(); | |
698 | ||
699 | // scroll to the requested page | |
700 | state->setScrollPosition(page, tileMap->getPageLeftX(page), | |
701 | tileMap->getPageTopY(page)); | |
702 | ||
703 | // scroll the requested point to the center of the window | |
704 | cvtUserToWindow(page, x, y, &wx, &wy); | |
705 | sx = state->getScrollX() + wx - state->getWinW() / 2; | |
706 | sy = state->getScrollY() + wy - state->getWinH() / 2; | |
707 | state->setScrollPosition(page, sx, sy); | |
708 | ||
709 | finishUpdate(gTrue, gFalse); | |
710 | 692 | } |
711 | 693 | |
712 | 694 | void PDFCore::setZoom(double zoom) { |
147 | 147 | virtual void scrollToBottomEdge(); |
148 | 148 | virtual void scrollToTopLeft(); |
149 | 149 | virtual void scrollToBottomRight(); |
150 | // Scroll so that (page, x, y) is centered in the window. | |
151 | virtual void scrollToCentered(int page, double x, double y); | |
152 | 150 | virtual void setZoom(double zoom); |
153 | 151 | virtual void zoomToRect(int page, double ulx, double uly, |
154 | 152 | double lrx, double lry); |
231 | 231 | fileNameU = NULL; |
232 | 232 | #endif |
233 | 233 | } |
234 | str = strA; | |
235 | 234 | ok = setup(ownerPassword, userPassword); |
236 | 235 | } |
237 | 236 |
1923 | 1923 | skip = gFalse; |
1924 | 1924 | if ((xObjDict.dictGetValNF(i, &xObjRef)->isRef())) { |
1925 | 1925 | ref0 = xObjRef.getRef(); |
1926 | if (ref0.num < 0 || ref0.num >= xref->getNumObjects()) { | |
1927 | skip = gTrue; | |
1928 | } else { | |
1929 | skip = (GBool)visitedResources[ref0.num]; | |
1930 | visitedResources[ref0.num] = 1; | |
1931 | } | |
1926 | skip = (GBool)visitedResources[ref0.num]; | |
1927 | visitedResources[ref0.num] = 1; | |
1932 | 1928 | } |
1933 | 1929 | if (!skip) { |
1934 | 1930 | |
1959 | 1955 | skip = gFalse; |
1960 | 1956 | if ((patDict.dictGetValNF(i, &patRef)->isRef())) { |
1961 | 1957 | ref0 = patRef.getRef(); |
1962 | if (ref0.num < 0 || ref0.num >= xref->getNumObjects()) { | |
1963 | skip = gTrue; | |
1964 | } else { | |
1965 | skip = (GBool)visitedResources[ref0.num]; | |
1966 | visitedResources[ref0.num] = 1; | |
1967 | } | |
1958 | skip = (GBool)visitedResources[ref0.num]; | |
1959 | visitedResources[ref0.num] = 1; | |
1968 | 1960 | } |
1969 | 1961 | if (!skip) { |
1970 | 1962 | |
1995 | 1987 | skip = gFalse; |
1996 | 1988 | if ((gsDict.dictGetValNF(i, &gsRef)->isRef())) { |
1997 | 1989 | ref0 = gsRef.getRef(); |
1998 | if (ref0.num < 0 || ref0.num >= xref->getNumObjects()) { | |
1999 | skip = gTrue; | |
2000 | } else { | |
2001 | skip = (GBool)visitedResources[ref0.num]; | |
2002 | visitedResources[ref0.num] = 1; | |
2003 | } | |
1990 | skip = (GBool)visitedResources[ref0.num]; | |
1991 | visitedResources[ref0.num] = 1; | |
2004 | 1992 | } |
2005 | 1993 | if (!skip) { |
2006 | 1994 |
234 | 234 | if (ownerKeyObj.getString()->getLength() != 32 || |
235 | 235 | userKeyObj.getString()->getLength() != 32) { |
236 | 236 | error(errSyntaxError, -1, "Invalid encryption key length"); |
237 | // this is non-fatal -- see below | |
237 | goto done; | |
238 | 238 | } |
239 | 239 | } else if (encRevision <= 6) { |
240 | 240 | // the spec says 48 bytes, but Acrobat pads them out longer |
251 | 251 | permFlags = permObj.getInt(); |
252 | 252 | ownerKey = ownerKeyObj.getString()->copy(); |
253 | 253 | userKey = userKeyObj.getString()->copy(); |
254 | if (encRevision <= 4) { | |
255 | // Adobe apparently zero-pads the U value (and maybe the O value?) | |
256 | // if it's short | |
257 | while (ownerKey->getLength() < 32) { | |
258 | ownerKey->append((char)0x00); | |
259 | } | |
260 | while (userKey->getLength() < 32) { | |
261 | userKey->append((char)0x00); | |
262 | } | |
263 | } | |
264 | 254 | if (encVersion >= 1 && encVersion <= 2 && |
265 | 255 | encRevision >= 2 && encRevision <= 3) { |
266 | 256 | if (fileIDObj.isArray()) { |
4174 | 4174 | |
4175 | 4175 | if (str->getKind() == strJPX && |
4176 | 4176 | *width * *height > 10000000) { |
4177 | sw = (double)*width / (fabs(ctm[0]) + fabs(ctm[1])); | |
4178 | sh = (double)*height / (fabs(ctm[2]) + fabs(ctm[3])); | |
4177 | sw = (double)*width / (fabs(ctm[2]) + fabs(ctm[3])); | |
4178 | sh = (double)*height / (fabs(ctm[0]) + fabs(ctm[1])); | |
4179 | 4179 | if (sw > 8 && sh > 8) { |
4180 | 4180 | reduction = 3; |
4181 | 4181 | } else if (sw > 4 && sh > 4) { |
13 | 13 | //------------------------------------------------------------------------ |
14 | 14 | |
15 | 15 | // xpdf version |
16 | #define xpdfVersion "4.01.01" | |
16 | #define xpdfVersion "4.01" | |
17 | 17 | #define xpdfVersionNum 4.01 |
18 | 18 | #define xpdfMajorVersion 4 |
19 | 19 | #define xpdfMinorVersion 1 |
20 | #define xpdfUpdateVersion 1 | |
20 | #define xpdfUpdateVersion 0 | |
21 | 21 | #define xpdfMajorVersionStr "4" |
22 | 22 | #define xpdfMinorVersionStr "1" |
23 | #define xpdfUpdateVersionStr "1" | |
23 | #define xpdfUpdateVersionStr "0" | |
24 | 24 | |
25 | 25 | // supported PDF version |
26 | 26 | #define supportedPDFVersionStr "2.0" |
30 | 30 | #define xpdfCopyright "Copyright 1996-2019 Glyph & Cog, LLC" |
31 | 31 | |
32 | 32 | // Windows resource file stuff |
33 | #define winxpdfVersion "WinXpdf 4.01.01" | |
33 | #define winxpdfVersion "WinXpdf 4.01" | |
34 | 34 | #define xpdfCopyrightAmp "Copyright 1996-2019 Glyph && Cog, LLC" |
35 | 35 | |
36 | 36 | //------------------------------------------------------------------------ |
45 | 45 | static void scanFonts(Object *obj, PDFDoc *doc); |
46 | 46 | static void scanFonts(Dict *resDict, PDFDoc *doc); |
47 | 47 | static void scanFont(GfxFont *font, PDFDoc *doc); |
48 | static GBool checkObject(Object *in, Object *out); | |
49 | 48 | |
50 | 49 | static int firstPage = 1; |
51 | 50 | static int lastPage = 0; |
85 | 84 | {NULL} |
86 | 85 | }; |
87 | 86 | |
88 | static PDFDoc *doc; | |
89 | ||
90 | 87 | static Ref *fonts; |
91 | 88 | static int fontsLen; |
92 | 89 | static int fontsSize; |
93 | 90 | |
94 | static char *seenObjs; | |
95 | static int numObjects; | |
91 | static Ref *seenObjs; | |
92 | static int seenObjsLen; | |
93 | static int seenObjsSize; | |
96 | 94 | |
97 | 95 | int main(int argc, char *argv[]) { |
96 | PDFDoc *doc; | |
98 | 97 | char *fileName; |
99 | 98 | GString *ownerPW, *userPW; |
100 | 99 | GBool ok; |
166 | 165 | } |
167 | 166 | fonts = NULL; |
168 | 167 | fontsLen = fontsSize = 0; |
169 | numObjects = doc->getXRef()->getNumObjects(); | |
170 | seenObjs = (char *)gmalloc(numObjects); | |
171 | memset(seenObjs, 0, numObjects); | |
168 | seenObjs = NULL; | |
169 | seenObjsLen = seenObjsSize = 0; | |
172 | 170 | for (pg = firstPage; pg <= lastPage; ++pg) { |
173 | 171 | page = doc->getCatalog()->getPage(pg); |
174 | 172 | if ((resDict = page->getResourceDict())) { |
221 | 219 | |
222 | 220 | static void scanFonts(Object *obj, PDFDoc *doc) { |
223 | 221 | Object obj2; |
224 | ||
225 | if (checkObject(obj, &obj2) && obj2.isDict()) { | |
222 | int i; | |
223 | ||
224 | if (obj->isRef()) { | |
225 | for (i = 0; i < seenObjsLen; ++i) { | |
226 | if (obj->getRefNum() == seenObjs[i].num && | |
227 | obj->getRefGen() == seenObjs[i].gen) { | |
228 | return; | |
229 | } | |
230 | } | |
231 | if (seenObjsLen == seenObjsSize) { | |
232 | if (seenObjsSize <= INT_MAX - 32) { | |
233 | seenObjsSize += 32; | |
234 | } else { | |
235 | // let greallocn throw an exception | |
236 | seenObjsSize = -1; | |
237 | } | |
238 | seenObjs = (Ref *)greallocn(seenObjs, seenObjsSize, sizeof(Ref)); | |
239 | } | |
240 | seenObjs[seenObjsLen++] = obj->getRef(); | |
241 | } | |
242 | if (obj->fetch(doc->getXRef(), &obj2)->isDict()) { | |
226 | 243 | scanFonts(obj2.getDict(), doc); |
227 | 244 | } |
228 | 245 | obj2.free(); |
229 | 246 | } |
230 | 247 | |
231 | 248 | static void scanFonts(Dict *resDict, PDFDoc *doc) { |
232 | Object fontDict1, fontDict2, xObjDict1, xObjDict2, xObj1, xObj2; | |
233 | Object patternDict1, patternDict2, pattern1, pattern2; | |
234 | Object gsDict1, gsDict2, gs1, gs2, smask1, smask2, smaskGroup1, smaskGroup2; | |
235 | Object resObj; | |
249 | Object obj1, obj2, xObjDict, xObj; | |
250 | Object patternDict, pattern, gsDict, gs, smask, smaskGroup, resObj; | |
236 | 251 | Ref r; |
237 | 252 | GfxFontDict *gfxFontDict; |
238 | 253 | GfxFont *font; |
240 | 255 | |
241 | 256 | // scan the fonts in this resource dictionary |
242 | 257 | gfxFontDict = NULL; |
243 | resDict->lookupNF("Font", &fontDict1); | |
244 | if (checkObject(&fontDict1, &fontDict2) && fontDict2.isDict()) { | |
245 | if (fontDict1.isRef()) { | |
246 | r = fontDict1.getRef(); | |
247 | gfxFontDict = new GfxFontDict(doc->getXRef(), &r, fontDict2.getDict()); | |
248 | } else { | |
249 | gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, fontDict2.getDict()); | |
250 | } | |
251 | if (gfxFontDict) { | |
252 | for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { | |
253 | if ((font = gfxFontDict->getFont(i))) { | |
254 | scanFont(font, doc); | |
255 | } | |
256 | } | |
257 | delete gfxFontDict; | |
258 | } | |
259 | } | |
260 | fontDict2.free(); | |
261 | fontDict1.free(); | |
258 | resDict->lookupNF("Font", &obj1); | |
259 | if (obj1.isRef()) { | |
260 | obj1.fetch(doc->getXRef(), &obj2); | |
261 | if (obj2.isDict()) { | |
262 | r = obj1.getRef(); | |
263 | gfxFontDict = new GfxFontDict(doc->getXRef(), &r, obj2.getDict()); | |
264 | } | |
265 | obj2.free(); | |
266 | } else if (obj1.isDict()) { | |
267 | gfxFontDict = new GfxFontDict(doc->getXRef(), NULL, obj1.getDict()); | |
268 | } | |
269 | if (gfxFontDict) { | |
270 | for (i = 0; i < gfxFontDict->getNumFonts(); ++i) { | |
271 | if ((font = gfxFontDict->getFont(i))) { | |
272 | scanFont(font, doc); | |
273 | } | |
274 | } | |
275 | delete gfxFontDict; | |
276 | } | |
277 | obj1.free(); | |
262 | 278 | |
263 | 279 | // recursively scan any resource dictionaries in XObjects in this |
264 | 280 | // resource dictionary |
265 | resDict->lookupNF("XObject", &xObjDict1); | |
266 | if (checkObject(&xObjDict1, &xObjDict2) && xObjDict2.isDict()) { | |
267 | for (i = 0; i < xObjDict2.dictGetLength(); ++i) { | |
268 | xObjDict2.dictGetValNF(i, &xObj1); | |
269 | if (checkObject(&xObj1, &xObj2) && xObj2.isStream()) { | |
270 | xObj2.streamGetDict()->lookupNF("Resources", &resObj); | |
281 | resDict->lookup("XObject", &xObjDict); | |
282 | if (xObjDict.isDict()) { | |
283 | for (i = 0; i < xObjDict.dictGetLength(); ++i) { | |
284 | xObjDict.dictGetVal(i, &xObj); | |
285 | if (xObj.isStream()) { | |
286 | xObj.streamGetDict()->lookupNF("Resources", &resObj); | |
271 | 287 | scanFonts(&resObj, doc); |
272 | 288 | resObj.free(); |
273 | 289 | } |
274 | xObj2.free(); | |
275 | xObj1.free(); | |
276 | } | |
277 | } | |
278 | xObjDict2.free(); | |
279 | xObjDict1.free(); | |
290 | xObj.free(); | |
291 | } | |
292 | } | |
293 | xObjDict.free(); | |
280 | 294 | |
281 | 295 | // recursively scan any resource dictionaries in Patterns in this |
282 | 296 | // resource dictionary |
283 | resDict->lookupNF("Pattern", &patternDict1); | |
284 | if (checkObject(&patternDict1, &patternDict2) && patternDict2.isDict()) { | |
285 | for (i = 0; i < patternDict2.dictGetLength(); ++i) { | |
286 | patternDict2.dictGetValNF(i, &pattern1); | |
287 | if (checkObject(&pattern1, &pattern2) && pattern2.isStream()) { | |
288 | pattern2.streamGetDict()->lookupNF("Resources", &resObj); | |
297 | resDict->lookup("Pattern", &patternDict); | |
298 | if (patternDict.isDict()) { | |
299 | for (i = 0; i < patternDict.dictGetLength(); ++i) { | |
300 | patternDict.dictGetVal(i, &pattern); | |
301 | if (pattern.isStream()) { | |
302 | pattern.streamGetDict()->lookupNF("Resources", &resObj); | |
289 | 303 | scanFonts(&resObj, doc); |
290 | 304 | resObj.free(); |
291 | 305 | } |
292 | pattern2.free(); | |
293 | pattern1.free(); | |
294 | } | |
295 | } | |
296 | patternDict2.free(); | |
297 | patternDict1.free(); | |
306 | pattern.free(); | |
307 | } | |
308 | } | |
309 | patternDict.free(); | |
298 | 310 | |
299 | 311 | // recursively scan any resource dictionaries in ExtGStates in this |
300 | 312 | // resource dictionary |
301 | resDict->lookupNF("ExtGState", &gsDict1); | |
302 | if (checkObject(&gsDict1, &gsDict2) && gsDict2.isDict()) { | |
303 | for (i = 0; i < gsDict2.dictGetLength(); ++i) { | |
304 | gsDict1.dictGetValNF(i, &gs1); | |
305 | if (checkObject(&gs1, &gs2) && gs2.isDict()) { | |
306 | gs2.dictLookupNF("SMask", &smask1); | |
307 | if (checkObject(&smask1, &smask2) && smask2.isDict()) { | |
308 | smask2.dictLookupNF("G", &smaskGroup1); | |
309 | if (checkObject(&smaskGroup1, &smaskGroup2) && | |
310 | smaskGroup2.isStream()) { | |
311 | smaskGroup2.streamGetDict()->lookupNF("Resources", &resObj); | |
313 | resDict->lookup("ExtGState", &gsDict); | |
314 | if (gsDict.isDict()) { | |
315 | for (i = 0; i < gsDict.dictGetLength(); ++i) { | |
316 | if (gsDict.dictGetVal(i, &gs)->isDict()) { | |
317 | if (gs.dictLookup("SMask", &smask)->isDict()) { | |
318 | if (smask.dictLookup("G", &smaskGroup)->isStream()) { | |
319 | smaskGroup.streamGetDict()->lookupNF("Resources", &resObj); | |
312 | 320 | scanFonts(&resObj, doc); |
313 | 321 | resObj.free(); |
314 | 322 | } |
315 | smaskGroup2.free(); | |
316 | smaskGroup1.free(); | |
323 | smaskGroup.free(); | |
317 | 324 | } |
318 | smask2.free(); | |
319 | smask1.free(); | |
320 | } | |
321 | gs2.free(); | |
322 | gs1.free(); | |
323 | } | |
324 | } | |
325 | gsDict2.free(); | |
326 | gsDict1.free(); | |
325 | smask.free(); | |
326 | } | |
327 | gs.free(); | |
328 | } | |
329 | } | |
330 | gsDict.free(); | |
327 | 331 | } |
328 | 332 | |
329 | 333 | static void scanFont(GfxFont *font, PDFDoc *doc) { |
427 | 431 | } |
428 | 432 | fonts[fontsLen++] = *font->getID(); |
429 | 433 | } |
430 | ||
431 | static GBool checkObject(Object *in, Object *out) { | |
432 | int objNum; | |
433 | ||
434 | if (!in->isRef()) { | |
435 | in->copy(out); | |
436 | return gTrue; | |
437 | } | |
438 | objNum = in->getRefNum(); | |
439 | if (objNum < 0 || objNum >= numObjects) { | |
440 | out->initNull(); | |
441 | return gTrue; | |
442 | } | |
443 | if (seenObjs[objNum]) { | |
444 | out->initNull(); | |
445 | return gFalse; | |
446 | } | |
447 | seenObjs[objNum] = (char)1; | |
448 | in->fetch(doc->getXRef(), out); | |
449 | return gTrue; | |
450 | } |
0 | 2019-05-05 Hironobu Yamashita <h.y.acetaminophen@gmail.com> | |
1 | ||
2 | * bibtexu-yannis.test, yannis.aux, yannis.bib, yannis.bbl: | |
3 | New test files for BibTeXu. | |
4 | * Makefile.am: Add the new test. | |
5 | ||
6 | 0 | 2019-03-15 Hironobu Yamashita <h.y.acetaminophen@gmail.com> |
7 | 1 | |
8 | 2 | * Makefile.am: Add bibtex8.1 and bibtexu.1. |
75 | 75 | ## Tests. |
76 | 76 | ## |
77 | 77 | bibtex8_tests = tests/bibtex8.test tests/bibtex8-mem.test tests/sort.test |
78 | bibtexu_tests = tests/bibtexu.test tests/bibtexu-yannis.test | |
78 | bibtexu_tests = tests/bibtexu.test | |
79 | 79 | |
80 | 80 | TESTS = |
81 | 81 | if BIBTEX8 |
85 | 85 | if BIBTEXU |
86 | 86 | TESTS += $(bibtexu_tests) |
87 | 87 | endif BIBTEXU |
88 | tests/bibtexu.log tests/bibtexu-yannis.log: bibtexu$(EXEEXT) | |
88 | tests/bibtexu.log: bibtexu$(EXEEXT) | |
89 | 89 | |
90 | 90 | EXTRA_DIST = $(bibtex8_tests) $(bibtexu_tests) |
91 | 91 | DISTCLEANFILES = |
100 | 100 | DISTCLEANFILES += tests/xsort.aux tests/xsort.bbl tests/xsort.blg |
101 | 101 | ## tests/bibtex8-mem.test |
102 | 102 | DISTCLEANFILES += tests/memtest.bib tests/memtest?.* |
103 | ## tests/bibtexu-yannis.test | |
104 | EXTRA_DIST += tests/yannis.aux tests/yannis.bbl tests/yannis.bib | |
105 | DISTCLEANFILES += tests/xyannis.aux tests/xyannis.bbl tests/xyannis.blg | |
106 | 103 | |
107 | 104 | ## Not used |
108 | 105 | ## |
645 | 645 | file_id.diz |
646 | 646 | |
647 | 647 | bibtex8_tests = tests/bibtex8.test tests/bibtex8-mem.test tests/sort.test |
648 | bibtexu_tests = tests/bibtexu.test tests/bibtexu-yannis.test | |
648 | bibtexu_tests = tests/bibtexu.test | |
649 | 649 | TESTS = $(am__append_3) $(am__append_4) |
650 | 650 | EXTRA_DIST = $(bibtex8_tests) $(bibtexu_tests) tests/sort.aux \ |
651 | 651 | tests/sort1.bbl tests/sort2.bbl tests/sort3.bbl \ |
652 | 652 | tests/sort1.csf tests/sort2.csf tests/sort3.csf \ |
653 | tests/testdata.bib tests/teststyle.bst tests/yannis.aux \ | |
654 | tests/yannis.bbl tests/yannis.bib bt371csf.zip dos-dj.mak \ | |
653 | tests/testdata.bib tests/teststyle.bst bt371csf.zip dos-dj.mak \ | |
655 | 654 | dos-emx.mak os2.mak unix.mak csf/00readme.txt csf/COPYING \ |
656 | 655 | csf/HISTORY csf/file_id.diz |
657 | 656 | DISTCLEANFILES = tests/xexampl.aux tests/xexampl.bbl tests/xexampl.blg \ |
658 | 657 | tests/xsort.aux tests/xsort.bbl tests/xsort.blg \ |
659 | tests/memtest.bib tests/memtest?.* tests/xyannis.aux \ | |
660 | tests/xyannis.bbl tests/xyannis.blg | |
658 | tests/memtest.bib tests/memtest?.* | |
661 | 659 | all: config.h |
662 | 660 | $(MAKE) $(AM_MAKEFLAGS) all-am |
663 | 661 | |
1672 | 1670 | @KPATHSEA_RULE@ |
1673 | 1671 | @ICU_RULE@ |
1674 | 1672 | tests/bibtex8.log tests/bibtex8-mem.log tests/sort.log: bibtex8$(EXEEXT) |
1675 | tests/bibtexu.log tests/bibtexu-yannis.log: bibtexu$(EXEEXT) | |
1673 | tests/bibtexu.log: bibtexu$(EXEEXT) | |
1676 | 1674 | |
1677 | 1675 | # Tell versions [3.59,3.63) of GNU make to not export all variables. |
1678 | 1676 | # Otherwise a system limit (for SysV at least) may be exceeded. |
0 | #! /bin/sh -vx | |
1 | # $Id: bibtexu-yannis.test 45809 2017-11-15 00:36:56Z karl $ | |
2 | # Copyright 2019 Karl Berry <tex-live@tug.org> | |
3 | # You may freely use, modify and/or distribute this file. | |
4 | ||
5 | # Test file prepared by Yannis in 2009. | |
6 | ||
7 | test -d tests || mkdir -p tests | |
8 | ||
9 | cp $srcdir/tests/yannis.aux tests/xyannis.aux | |
10 | ||
11 | TEXMFCNF=$srcdir/../kpathsea \ | |
12 | BSTINPUTS=$srcdir/../web2c/tests \ | |
13 | BIBINPUTS=$srcdir/tests \ | |
14 | ./bibtexu -l fr -o fr tests/xyannis || exit 1 | |
15 | ||
16 | diff $srcdir/tests/yannis.bbl tests/xyannis.bbl || exit 1 | |
17 |
0 | \begin{thebibliography}{} | |
1 | ||
2 | \bibitem[Échelon, 2009]{cle2} | |
3 | Échelon, N. (2009). | |
4 | \newblock {\em La vie est un long fleuve tranquille}. | |
5 | \newblock Les Éditions du désastre. | |
6 | ||
7 | \bibitem[Œtingen, 2009]{cle8} | |
8 | Œtingen, N. (2009). | |
9 | \newblock {\em Un livre}. | |
10 | \newblock Les Éditions du désastre. | |
11 | ||
12 | \bibitem[Tarantin, 2009]{cle4} | |
13 | Tarantin, N. (2009). | |
14 | \newblock {\em En revenant de Tarascon}. | |
15 | \newblock Les Éditions du désastre. | |
16 | ||
17 | \bibitem[Διογένης, 2009]{cle1} | |
18 | Διογένης (2009). | |
19 | \newblock {\em Μήπως εἴδατε τὸ φανάρι μου;}. | |
20 | \newblock Τὰ σοφὰ βιβλία. | |
21 | ||
22 | \bibitem[Ἕλληνας, 2009]{cle7} | |
23 | Ἕλληνας, Μ. (2009). | |
24 | \newblock {\em Τὸ καλὸ παράδειγμα}. | |
25 | \newblock Ἐκδοτικὸς οἶκος «Δὲν βαριέσαι». | |
26 | ||
27 | \bibitem[Ζαχαρόπουλος, 2009]{cle5} | |
28 | Ζαχαρόπουλος, Ζ. (2009). | |
29 | \newblock {\em Μοῦ λένε νὰ μὴν κλαίω, μὰ τί νὰ | |
30 | κάνω, ἀφοῦ σὲ χάνω}. | |
31 | \newblock Ἐκδόσεις τῶν χαμένων ἐλπίδων. | |
32 | ||
33 | \bibitem[天堂最新的章节表, 2009]{cle3} | |
34 | 天堂最新的章节表, 格. (2009). | |
35 | \newblock {\em 製版・文書処理システム Ω}. | |
36 | \newblock Les Éditions du désastre. | |
37 | ||
38 | \bibitem[天王最新章, 2009]{cle6} | |
39 | 天王最新章, 节. (2009). | |
40 | \newblock {\em 製版・文書処理システム Ω}. | |
41 | \newblock Les Éditions du désastre. | |
42 | ||
43 | \end{thebibliography} |
0 | ||
1 | @book{cle1, | |
2 | Author = {Διογένης}, | |
3 | Publisher = {Τὰ σοφὰ βιβλία}, | |
4 | Title = {Μήπως εἴδατε τὸ φανάρι μου;}, | |
5 | Year = {2009}} | |
6 | ||
7 | @book{cle2, | |
8 | Author = {Échelon, Nicolas}, | |
9 | Publisher = {Les Éditions du désastre}, | |
10 | Title = {La vie est un long fleuve tranquille}, | |
11 | Year = {2009}} | |
12 | ||
13 | @book{cle3, | |
14 | Author = {天堂最新的章节表, 格的儿子}, | |
15 | Publisher = {Les Éditions du désastre}, | |
16 | Title = {製版・文書処理システム Ω}, | |
17 | Year = {2009}} | |
18 | ||
19 | @book{cle4, | |
20 | Author = {Tarantin, Nicolas}, | |
21 | Publisher = {Les Éditions du désastre}, | |
22 | Title = {En revenant de Tarascon}, | |
23 | Year = {2009}} | |
24 | ||
25 | @book{cle5, | |
26 | Author = {Ζαχαρόπουλος, Ζαχαρίας}, | |
27 | Publisher = {Ἐκδόσεις τῶν χαμένων ἐλπίδων}, | |
28 | Title = {Μοῦ λένε νὰ μὴν κλαίω, μὰ τί νὰ κάνω, ἀφοῦ σὲ χάνω}, | |
29 | Year = {2009}} | |
30 | ||
31 | @book{cle6, | |
32 | Author = {天王最新章, 节列表}, | |
33 | Publisher = {Les Éditions du désastre}, | |
34 | Title = {製版・文書処理システム Ω}, | |
35 | Year = {2009}} | |
36 | ||
37 | @book{cle7, | |
38 | Author = {Ἕλληνας, Μῆτσος}, | |
39 | Publisher = {Ἐκδοτικὸς οἶκος «Δὲν βαριέσαι»}, | |
40 | Title = {Τὸ καλὸ παράδειγμα}, | |
41 | Year = {2009}} | |
42 | ||
43 | @book{cle8, | |
44 | Author = {Œtingen, Nicolas}, | |
45 | Publisher = {Les Éditions du désastre}, | |
46 | Title = {Un livre}, | |
47 | Year = {2009}} |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for TeX Live texk 2020/dev. | |
2 | # Generated by GNU Autoconf 2.69 for TeX Live texk 2019. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-live@tug.org>. |
5 | 5 | # |
578 | 578 | # Identity of this package. |
579 | 579 | PACKAGE_NAME='TeX Live texk' |
580 | 580 | PACKAGE_TARNAME='tex-live-texk' |
581 | PACKAGE_VERSION='2020/dev' | |
582 | PACKAGE_STRING='TeX Live texk 2020/dev' | |
581 | PACKAGE_VERSION='2019' | |
582 | PACKAGE_STRING='TeX Live texk 2019' | |
583 | 583 | PACKAGE_BUGREPORT='tex-live@tug.org' |
584 | 584 | PACKAGE_URL='' |
585 | 585 | |
1392 | 1392 | # Omit some internal or obsolete options to make the list less imposing. |
1393 | 1393 | # This message is too long to be a string in the A/UX 3.1 sh. |
1394 | 1394 | cat <<_ACEOF |
1395 | \`configure' configures TeX Live texk 2020/dev to adapt to many kinds of systems. | |
1395 | \`configure' configures TeX Live texk 2019 to adapt to many kinds of systems. | |
1396 | 1396 | |
1397 | 1397 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1398 | 1398 | |
1462 | 1462 | |
1463 | 1463 | if test -n "$ac_init_help"; then |
1464 | 1464 | case $ac_init_help in |
1465 | short | recursive ) echo "Configuration of TeX Live texk 2020/dev:";; | |
1465 | short | recursive ) echo "Configuration of TeX Live texk 2019:";; | |
1466 | 1466 | esac |
1467 | 1467 | cat <<\_ACEOF |
1468 | 1468 | |
1748 | 1748 | test -n "$ac_init_help" && exit $ac_status |
1749 | 1749 | if $ac_init_version; then |
1750 | 1750 | cat <<\_ACEOF |
1751 | TeX Live texk configure 2020/dev | |
1751 | TeX Live texk configure 2019 | |
1752 | 1752 | generated by GNU Autoconf 2.69 |
1753 | 1753 | |
1754 | 1754 | Copyright (C) 2012 Free Software Foundation, Inc. |
1849 | 1849 | This file contains any messages produced by compilers while |
1850 | 1850 | running configure, to aid debugging if configure makes a mistake. |
1851 | 1851 | |
1852 | It was created by TeX Live texk $as_me 2020/dev, which was | |
1852 | It was created by TeX Live texk $as_me 2019, which was | |
1853 | 1853 | generated by GNU Autoconf 2.69. Invocation command line was |
1854 | 1854 | |
1855 | 1855 | $ $0 $@ |
6058 | 6058 | |
6059 | 6059 | # Define the identity of the package. |
6060 | 6060 | PACKAGE='tex-live-texk' |
6061 | VERSION='2020/dev' | |
6061 | VERSION='2019' | |
6062 | 6062 | |
6063 | 6063 | |
6064 | 6064 | cat >>confdefs.h <<_ACEOF |
7099 | 7099 | # report actual input values of CONFIG_FILES etc. instead of their |
7100 | 7100 | # values after options handling. |
7101 | 7101 | ac_log=" |
7102 | This file was extended by TeX Live texk $as_me 2020/dev, which was | |
7102 | This file was extended by TeX Live texk $as_me 2019, which was | |
7103 | 7103 | generated by GNU Autoconf 2.69. Invocation command line was |
7104 | 7104 | |
7105 | 7105 | CONFIG_FILES = $CONFIG_FILES |
7156 | 7156 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
7157 | 7157 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
7158 | 7158 | ac_cs_version="\\ |
7159 | TeX Live texk config.status 2020/dev | |
7159 | TeX Live texk config.status 2019 | |
7160 | 7160 | configured by $0, generated by GNU Autoconf 2.69, |
7161 | 7161 | with options \\"\$ac_cs_config\\" |
7162 | 7162 |
13475 | 13475 | |
13476 | 13476 | |
13477 | 13477 | |
13478 | $as_echo "#define TL_VERSION \"TeX Live 2020/dev\"" >>confdefs.h | |
13478 | $as_echo "#define TL_VERSION \"TeX Live 2019\"" >>confdefs.h | |
13479 | 13479 | |
13480 | 13480 | |
13481 | 13481 | kpse_save_CPPFLAGS=$CPPFLAGS |
0 | 2019-05-08 Akira Kakuto <kakuto@w32tex.org> | |
1 | ||
2 | * dpxfile.c: Avoid buffer overflow. | |
3 | ||
4 | 2019-05-08 Shunsaku Hirata <shunsaku.hirata74@gmail.com> | |
5 | ||
6 | * spc_pdfm.c: Transformation also applies to annotations | |
7 | created by pdf:ann. | |
8 | ||
0 | 9 | 2019-05-07 Shunsaku Hirata <shunsaku.hirata74@gmail.com> |
1 | 10 | |
2 | 11 | * tt_cmap.c: Fix a bug that CFF charset data were not read. |
162 | 162 | extern int utf8name_failed; |
163 | 163 | #endif /* WIN32 */ |
164 | 164 | |
165 | #define CMDBUFSIZ 1024 | |
165 | 166 | static int exec_spawn (char *cmd) |
166 | 167 | { |
167 | 168 | char **cmdv, **qv; |
168 | 169 | char *p, *pp; |
169 | char buf[1024]; | |
170 | char buf[CMDBUFSIZ]; | |
171 | int charcnt; | |
170 | 172 | int i, ret = -1; |
171 | 173 | #ifdef WIN32 |
172 | 174 | wchar_t **cmdvw, **qvw; |
185 | 187 | i++; |
186 | 188 | p++; |
187 | 189 | } |
188 | cmdv = xcalloc (i + 2, sizeof (char *)); | |
190 | cmdv = xcalloc (i + 4, sizeof (char *)); | |
189 | 191 | p = cmd; |
190 | 192 | qv = cmdv; |
191 | 193 | while (*p) { |
192 | 194 | pp = buf; |
195 | charcnt = 0; | |
193 | 196 | if (*p == '"') { |
194 | 197 | p++; |
195 | 198 | while (*p != '"') { |
197 | 200 | goto done; |
198 | 201 | } |
199 | 202 | *pp++ = *p++; |
203 | charcnt++; | |
204 | if (charcnt > CMDBUFSIZ - 1) { | |
205 | ERROR("Too long a command line."); | |
206 | } | |
200 | 207 | } |
201 | 208 | p++; |
202 | 209 | } else if (*p == '\'') { |
206 | 213 | goto done; |
207 | 214 | } |
208 | 215 | *pp++ = *p++; |
216 | charcnt++; | |
217 | if (charcnt > CMDBUFSIZ - 1) { | |
218 | ERROR("Too long a command line."); | |
219 | } | |
209 | 220 | } |
210 | 221 | p++; |
211 | 222 | } else { |
217 | 228 | goto done; |
218 | 229 | } |
219 | 230 | *pp++ = *p++; |
231 | charcnt++; | |
232 | if (charcnt > CMDBUFSIZ - 1) { | |
233 | ERROR("Too long a command line."); | |
234 | } | |
220 | 235 | } |
221 | 236 | p++; |
222 | 237 | } else { |
223 | 238 | *pp++ = *p++; |
239 | charcnt++; | |
240 | if (charcnt > CMDBUFSIZ - 1) { | |
241 | ERROR("Too long a command line."); | |
242 | } | |
224 | 243 | } |
225 | 244 | } |
226 | 245 | } |
238 | 257 | p++; |
239 | 258 | qv++; |
240 | 259 | } |
260 | *qv = NULL; | |
261 | ||
241 | 262 | #ifdef WIN32 |
242 | 263 | #if defined(MIKTEX) |
243 | 264 | ret = _spawnvp(_P_WAIT, *cmdv, (const char* const*)cmdv); |
244 | 265 | #else |
245 | cmdvw = xcalloc (i + 2, sizeof (wchar_t *)); | |
266 | cmdvw = xcalloc (i + 4, sizeof (wchar_t *)); | |
246 | 267 | if (utf8name_failed == 0) { |
247 | 268 | qv = cmdv; |
248 | 269 | qvw = cmdvw; |
596 | 596 | return dict; |
597 | 597 | } |
598 | 598 | |
599 | #define SPC_PDFM_SUPPORT_ANNOT_TRANS 1 | |
599 | 600 | static int |
600 | 601 | spc_handler_pdfm_annot (struct spc_env *spe, struct spc_arg *args) |
601 | 602 | { |
603 | 604 | pdf_obj *annot_dict; |
604 | 605 | pdf_rect rect; |
605 | 606 | char *ident = NULL; |
606 | pdf_coord cp; | |
607 | 607 | transform_info ti; |
608 | 608 | |
609 | 609 | skip_white(&args->curptr, args->endptr); |
641 | 641 | return -1; |
642 | 642 | } |
643 | 643 | |
644 | cp.x = spe->x_user; cp.y = spe->y_user; | |
645 | pdf_dev_transform(&cp, NULL); | |
646 | if (ti.flags & INFO_HAS_USER_BBOX) { | |
647 | rect.llx = ti.bbox.llx + cp.x; | |
648 | rect.lly = ti.bbox.lly + cp.y; | |
649 | rect.urx = ti.bbox.urx + cp.x; | |
650 | rect.ury = ti.bbox.ury + cp.y; | |
651 | } else { | |
652 | rect.llx = cp.x; | |
653 | rect.lly = cp.y - spe->mag * ti.depth; | |
654 | rect.urx = cp.x + spe->mag * ti.width; | |
655 | rect.ury = cp.y + spe->mag * ti.height; | |
656 | } | |
644 | #ifdef SPC_PDFM_SUPPORT_ANNOT_TRANS | |
645 | { | |
646 | pdf_coord cp1, cp2, cp3, cp4; | |
647 | /* QuadPoints not working? */ | |
648 | #ifdef USE_QUADPOINTS | |
649 | pdf_obj *qpoints; | |
650 | #endif | |
651 | if (ti.flags & INFO_HAS_USER_BBOX) { | |
652 | cp1.x = spe->x_user + ti.bbox.llx; | |
653 | cp1.y = spe->y_user + ti.bbox.lly; | |
654 | cp2.x = spe->x_user + ti.bbox.urx; | |
655 | cp2.y = spe->y_user + ti.bbox.lly; | |
656 | cp3.x = spe->x_user + ti.bbox.urx; | |
657 | cp3.y = spe->y_user + ti.bbox.ury; | |
658 | cp4.x = spe->x_user + ti.bbox.llx; | |
659 | cp4.y = spe->y_user + ti.bbox.ury; | |
660 | } else { | |
661 | cp1.x = spe->x_user; | |
662 | cp1.y = spe->y_user - spe->mag * ti.depth; | |
663 | cp2.x = spe->x_user + spe->mag * ti.width; | |
664 | cp2.y = spe->y_user - spe->mag * ti.depth; | |
665 | cp3.x = spe->x_user + spe->mag * ti.width; | |
666 | cp3.y = spe->y_user + spe->mag * ti.height; | |
667 | cp4.x = spe->x_user; | |
668 | cp4.y = spe->y_user + spe->mag * ti.height; | |
669 | } | |
670 | pdf_dev_transform(&cp1, NULL); | |
671 | pdf_dev_transform(&cp2, NULL); | |
672 | pdf_dev_transform(&cp3, NULL); | |
673 | pdf_dev_transform(&cp4, NULL); | |
674 | rect.llx = cp1.x; | |
675 | if (cp2.x < rect.llx) | |
676 | rect.llx = cp2.x; | |
677 | if (cp3.x < rect.llx) | |
678 | rect.llx = cp3.x; | |
679 | if (cp4.x < rect.llx) | |
680 | rect.llx = cp4.x; | |
681 | rect.urx = cp1.x; | |
682 | if (cp2.x > rect.urx) | |
683 | rect.urx = cp2.x; | |
684 | if (cp3.x > rect.urx) | |
685 | rect.urx = cp3.x; | |
686 | if (cp4.x > rect.urx) | |
687 | rect.urx = cp4.x; | |
688 | rect.lly = cp1.y; | |
689 | if (cp2.y < rect.lly) | |
690 | rect.lly = cp2.y; | |
691 | if (cp3.y < rect.lly) | |
692 | rect.lly = cp3.y; | |
693 | if (cp4.y < rect.lly) | |
694 | rect.lly = cp4.y; | |
695 | rect.ury = cp1.y; | |
696 | if (cp2.y > rect.ury) | |
697 | rect.ury = cp2.y; | |
698 | if (cp3.y > rect.ury) | |
699 | rect.ury = cp3.y; | |
700 | if (cp4.y > rect.ury) | |
701 | rect.ury = cp4.y; | |
702 | #ifdef USE_QUADPOINTS | |
703 | qpoints = pdf_new_array(); | |
704 | pdf_add_array(qpoints, pdf_new_number(ROUND(cp1.x, 0.01))); | |
705 | pdf_add_array(qpoints, pdf_new_number(ROUND(cp1.y, 0.01))); | |
706 | pdf_add_array(qpoints, pdf_new_number(ROUND(cp2.x, 0.01))); | |
707 | pdf_add_array(qpoints, pdf_new_number(ROUND(cp2.y, 0.01))); | |
708 | pdf_add_array(qpoints, pdf_new_number(ROUND(cp3.x, 0.01))); | |
709 | pdf_add_array(qpoints, pdf_new_number(ROUND(cp3.y, 0.01))); | |
710 | pdf_add_array(qpoints, pdf_new_number(ROUND(cp4.x, 0.01))); | |
711 | pdf_add_array(qpoints, pdf_new_number(ROUND(cp4.y, 0.01))); | |
712 | pdf_add_dict(annot_dict, pdf_new_name("QuadPoints"), qpoints); | |
713 | #endif | |
714 | } | |
715 | #else | |
716 | { | |
717 | pdf_coord cp; | |
718 | ||
719 | cp.x = spe->x_user; cp.y = spe->y_user; | |
720 | pdf_dev_transform(&cp, NULL); | |
721 | if (ti.flags & INFO_HAS_USER_BBOX) { | |
722 | rect.llx = ti.bbox.llx + cp.x; | |
723 | rect.lly = ti.bbox.lly + cp.y; | |
724 | rect.urx = ti.bbox.urx + cp.x; | |
725 | rect.ury = ti.bbox.ury + cp.y; | |
726 | } else { | |
727 | rect.llx = cp.x; | |
728 | rect.lly = cp.y - spe->mag * ti.depth; | |
729 | rect.urx = cp.x + spe->mag * ti.width; | |
730 | rect.ury = cp.y + spe->mag * ti.height; | |
731 | } | |
732 | } | |
733 | #endif | |
657 | 734 | |
658 | 735 | /* Order is important... */ |
659 | 736 | if (ident) |
0 | 2019-05-03 Akira Kakuto <kakuto@w32tex.org> | |
1 | ||
2 | * dvips.c, output.c, search.c: Support non-ascii file names | |
3 | in default code page of OS irrespective of values of a | |
4 | variable 'command_line_encoding' (Windows only). | |
5 | ||
6 | 0 | 2019-04-30 Karl Berry <karl@tug.org> |
7 | 1 | |
8 | 2 | * dosection.c (dosection): close PostScript string constant |
48 | 48 | #endif |
49 | 49 | |
50 | 50 | #if defined(WIN32) && defined(KPATHSEA) |
51 | FILE *generic_fsyscp_fopen(const char *filename, const char *mode) | |
52 | { | |
53 | FILE *f; | |
54 | ||
55 | f = fsyscp_fopen (filename, mode); | |
56 | ||
57 | if (f == NULL && file_system_codepage != win32_codepage) { | |
58 | int tmpcp = file_system_codepage; | |
59 | file_system_codepage = win32_codepage; | |
60 | f = fsyscp_fopen (filename, mode); | |
61 | file_system_codepage = tmpcp; | |
62 | } | |
63 | ||
64 | return f; | |
65 | } | |
66 | 51 | #undef fopen |
67 | #define fopen(file, fmode) generic_fsyscp_fopen(file, fmode) | |
52 | #define fopen(file, fmode) fsyscp_fopen(file, fmode) | |
68 | 53 | #endif |
69 | 54 | |
70 | 55 | #ifndef DEFRES |
19 | 19 | #undef fopen |
20 | 20 | #undef popen |
21 | 21 | #undef pclose |
22 | extern FILE *generic_fsyscp_fopen(const char *name, const char *mode); | |
23 | #define fopen(file, fmode) generic_fsyscp_fopen(file, fmode) | |
22 | #define fopen(file, fmode) fsyscp_fopen(file, fmode) | |
24 | 23 | #define popen(pcmd, pmode) fsyscp_popen(pcmd, pmode) |
25 | 24 | #define pclose(pstream) _pclose(pstream) |
26 | 25 | #endif |
157 | 156 | * or figure files to be installed in the .../ps directory. |
158 | 157 | */ |
159 | 158 | f = search(figpath, s, READBIN); |
160 | #if defined(WIN32) | |
161 | if (f == 0 && file_system_codepage != win32_codepage) { | |
162 | int tmpcp = file_system_codepage; | |
163 | file_system_codepage = win32_codepage; | |
164 | f = search(figpath, s, READBIN); | |
165 | file_system_codepage = tmpcp; | |
166 | } | |
167 | #endif | |
168 | 159 | if (f == 0) |
169 | 160 | f = search(headerpath, s, READBIN); |
170 | 161 | #if defined(VMCMS) || defined (MVSXA) |
23 | 23 | #undef fopen |
24 | 24 | #undef popen |
25 | 25 | #undef pclose |
26 | extern FILE *generic_fsyscp_fopen(const char *name, const char *mode); | |
27 | #define fopen(file, fmode) generic_fsyscp_fopen(file, fmode) | |
26 | #define fopen(file, fmode) fsyscp_fopen(file, fmode) | |
28 | 27 | #define popen(pcmd, pmode) fsyscp_popen(pcmd, pmode) |
29 | 28 | #define pclose(pstream) _pclose(pstream) |
30 | 29 | #endif |
0 | 2019-05-05 Karl Berry <karl@tug.org> | |
1 | ||
2 | * texmf.cnf: missed top 2018's. | |
3 | ||
4 | 2019-05-03 Karl Berry <karl@tug.org> | |
5 | ||
6 | * version.ac: 6.3.2/dev since TL'19 is released. | |
7 | ||
8 | 0 | 2019-04-07 Karl Berry <karl@freefriends.org> |
9 | 1 | |
10 | 2 | * TeX Live 2019. |
22 | 22 | #define KPATHSEA_C_AUTO_H |
23 | 23 | |
24 | 24 | /* kpathsea: the version string. */ |
25 | #define KPSEVERSION "kpathsea version 6.3.2/dev" | |
25 | #define KPSEVERSION "kpathsea version 6.3.1" | |
26 | 26 | |
27 | 27 | /* Define to 1 if the `closedir' function returns void instead of `int'. */ |
28 | 28 | #undef CLOSEDIR_VOID |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for Kpathsea 6.3.2/dev. | |
2 | # Generated by GNU Autoconf 2.69 for Kpathsea 6.3.1. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-k@tug.org>. |
5 | 5 | # |
589 | 589 | # Identity of this package. |
590 | 590 | PACKAGE_NAME='Kpathsea' |
591 | 591 | PACKAGE_TARNAME='kpathsea' |
592 | PACKAGE_VERSION='6.3.2/dev' | |
593 | PACKAGE_STRING='Kpathsea 6.3.2/dev' | |
592 | PACKAGE_VERSION='6.3.1' | |
593 | PACKAGE_STRING='Kpathsea 6.3.1' | |
594 | 594 | PACKAGE_BUGREPORT='tex-k@tug.org' |
595 | 595 | PACKAGE_URL='' |
596 | 596 | |
1338 | 1338 | # Omit some internal or obsolete options to make the list less imposing. |
1339 | 1339 | # This message is too long to be a string in the A/UX 3.1 sh. |
1340 | 1340 | cat <<_ACEOF |
1341 | \`configure' configures Kpathsea 6.3.2/dev to adapt to many kinds of systems. | |
1341 | \`configure' configures Kpathsea 6.3.1 to adapt to many kinds of systems. | |
1342 | 1342 | |
1343 | 1343 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1344 | 1344 | |
1408 | 1408 | |
1409 | 1409 | if test -n "$ac_init_help"; then |
1410 | 1410 | case $ac_init_help in |
1411 | short | recursive ) echo "Configuration of Kpathsea 6.3.2/dev:";; | |
1411 | short | recursive ) echo "Configuration of Kpathsea 6.3.1:";; | |
1412 | 1412 | esac |
1413 | 1413 | cat <<\_ACEOF |
1414 | 1414 | |
1536 | 1536 | test -n "$ac_init_help" && exit $ac_status |
1537 | 1537 | if $ac_init_version; then |
1538 | 1538 | cat <<\_ACEOF |
1539 | Kpathsea configure 6.3.2/dev | |
1539 | Kpathsea configure 6.3.1 | |
1540 | 1540 | generated by GNU Autoconf 2.69 |
1541 | 1541 | |
1542 | 1542 | Copyright (C) 2012 Free Software Foundation, Inc. |
2375 | 2375 | This file contains any messages produced by compilers while |
2376 | 2376 | running configure, to aid debugging if configure makes a mistake. |
2377 | 2377 | |
2378 | It was created by Kpathsea $as_me 6.3.2/dev, which was | |
2378 | It was created by Kpathsea $as_me 6.3.1, which was | |
2379 | 2379 | generated by GNU Autoconf 2.69. Invocation command line was |
2380 | 2380 | |
2381 | 2381 | $ $0 $@ |
2756 | 2756 | |
2757 | 2757 | |
2758 | 2758 | |
2759 | KPSEVERSION=6.3.2/dev | |
2760 | ||
2761 | ||
2762 | KPSE_LT_VERSINFO=9:2:3 | |
2763 | ||
2764 | ||
2765 | ||
2766 | WEB2CVERSION=" (TeX Live 2020/dev)" | |
2759 | KPSEVERSION=6.3.1 | |
2760 | ||
2761 | ||
2762 | KPSE_LT_VERSINFO=9:1:3 | |
2763 | ||
2764 | ||
2765 | ||
2766 | WEB2CVERSION=" (TeX Live 2019)" | |
2767 | 2767 | |
2768 | 2768 | |
2769 | 2769 | am__api_version='1.16' |
8072 | 8072 | |
8073 | 8073 | # Define the identity of the package. |
8074 | 8074 | PACKAGE='kpathsea' |
8075 | VERSION='6.3.2/dev' | |
8075 | VERSION='6.3.1' | |
8076 | 8076 | |
8077 | 8077 | |
8078 | 8078 | cat >>confdefs.h <<_ACEOF |
14696 | 14696 | # report actual input values of CONFIG_FILES etc. instead of their |
14697 | 14697 | # values after options handling. |
14698 | 14698 | ac_log=" |
14699 | This file was extended by Kpathsea $as_me 6.3.2/dev, which was | |
14699 | This file was extended by Kpathsea $as_me 6.3.1, which was | |
14700 | 14700 | generated by GNU Autoconf 2.69. Invocation command line was |
14701 | 14701 | |
14702 | 14702 | CONFIG_FILES = $CONFIG_FILES |
14762 | 14762 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
14763 | 14763 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
14764 | 14764 | ac_cs_version="\\ |
14765 | Kpathsea config.status 6.3.2/dev | |
14765 | Kpathsea config.status 6.3.1 | |
14766 | 14766 | configured by $0, generated by GNU Autoconf 2.69, |
14767 | 14767 | with options \\"\$ac_cs_config\\" |
14768 | 14768 |
3 | 3 | % If you modify this original file, YOUR CHANGES WILL BE LOST when it is |
4 | 4 | % updated. Instead, put your changes -- and only your changes, not an |
5 | 5 | % entire copy! -- in ../../texmf.cnf. That is, if this file is |
6 | % installed in /some/path/to/texlive/2019/texmf-dist/web2c/texmf.cnf, | |
7 | % add your custom settings to /some/path/to/texlive/2019/texmf.cnf. | |
8 | % (Below, we use YYYY in place of the specific year.) | |
6 | % installed in /some/path/to/texlive/2018/texmf-dist/web2c/texmf.cnf, | |
7 | % add your custom settings to /some/path/to/texlive/2018/texmf.cnf. | |
9 | 8 | % |
10 | 9 | % What follows is a super-summary of what this .cnf file can |
11 | 10 | % contain. Please read the Kpathsea manual for more information. |
19 | 19 | dnl -------------------------------------------------------- |
20 | 20 | dnl |
21 | 21 | dnl This file is m4-included from configure.ac. |
22 | m4_define([kpse_version], [6.3.2/dev]) | |
22 | m4_define([kpse_version], [6.3.1]) |
13461 | 13461 | |
13462 | 13462 | |
13463 | 13463 | |
13464 | $as_echo "#define TEX_LIVE_VERSION \"2020/dev\"" >>confdefs.h | |
13464 | $as_echo "#define TEX_LIVE_VERSION \"2019\"" >>confdefs.h | |
13465 | 13465 | |
13466 | 13466 | |
13467 | 13467 | for ac_header in ctype.h types.h locale.h |
13459 | 13459 | |
13460 | 13460 | |
13461 | 13461 | |
13462 | $as_echo "#define TL_VERSION \"TeX Live 2020/dev\"" >>confdefs.h | |
13462 | $as_echo "#define TL_VERSION \"TeX Live 2019\"" >>confdefs.h | |
13463 | 13463 | |
13464 | 13464 | |
13465 | 13465 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking if C99 variadic macros are supported" >&5 |
0 | 2019-05-03 Karl Berry <karl@tug.org> | |
1 | ||
2 | * version.ac: 1.3.8/dev since TL'19 is released. | |
3 | ||
4 | 0 | 2019-02-15 Akira Kakuto <kakuto@w32tex.org> |
5 | 1 | |
6 | 2 | * ptexenc.c: Initialize a local variable. |
5 | 5 | #define PTEXENC_C_AUTO_H |
6 | 6 | |
7 | 7 | /* ptexenc: the version string. */ |
8 | #define PTEXENCVERSION "ptexenc version 1.3.8/dev" | |
8 | #define PTEXENCVERSION "ptexenc version 1.3.7" | |
9 | 9 | |
10 | 10 | /* Define to 1 if the `closedir' function returns void instead of `int'. */ |
11 | 11 | #undef CLOSEDIR_VOID |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for ptexenc 1.3.8/dev. | |
2 | # Generated by GNU Autoconf 2.69 for ptexenc 1.3.7. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-k@tug.org>. |
5 | 5 | # |
589 | 589 | # Identity of this package. |
590 | 590 | PACKAGE_NAME='ptexenc' |
591 | 591 | PACKAGE_TARNAME='ptexenc' |
592 | PACKAGE_VERSION='1.3.8/dev' | |
593 | PACKAGE_STRING='ptexenc 1.3.8/dev' | |
592 | PACKAGE_VERSION='1.3.7' | |
593 | PACKAGE_STRING='ptexenc 1.3.7' | |
594 | 594 | PACKAGE_BUGREPORT='tex-k@tug.org' |
595 | 595 | PACKAGE_URL='' |
596 | 596 | |
1329 | 1329 | # Omit some internal or obsolete options to make the list less imposing. |
1330 | 1330 | # This message is too long to be a string in the A/UX 3.1 sh. |
1331 | 1331 | cat <<_ACEOF |
1332 | \`configure' configures ptexenc 1.3.8/dev to adapt to many kinds of systems. | |
1332 | \`configure' configures ptexenc 1.3.7 to adapt to many kinds of systems. | |
1333 | 1333 | |
1334 | 1334 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1335 | 1335 | |
1399 | 1399 | |
1400 | 1400 | if test -n "$ac_init_help"; then |
1401 | 1401 | case $ac_init_help in |
1402 | short | recursive ) echo "Configuration of ptexenc 1.3.8/dev:";; | |
1402 | short | recursive ) echo "Configuration of ptexenc 1.3.7:";; | |
1403 | 1403 | esac |
1404 | 1404 | cat <<\_ACEOF |
1405 | 1405 | |
1519 | 1519 | test -n "$ac_init_help" && exit $ac_status |
1520 | 1520 | if $ac_init_version; then |
1521 | 1521 | cat <<\_ACEOF |
1522 | ptexenc configure 1.3.8/dev | |
1522 | ptexenc configure 1.3.7 | |
1523 | 1523 | generated by GNU Autoconf 2.69 |
1524 | 1524 | |
1525 | 1525 | Copyright (C) 2012 Free Software Foundation, Inc. |
2175 | 2175 | This file contains any messages produced by compilers while |
2176 | 2176 | running configure, to aid debugging if configure makes a mistake. |
2177 | 2177 | |
2178 | It was created by ptexenc $as_me 1.3.8/dev, which was | |
2178 | It was created by ptexenc $as_me 1.3.7, which was | |
2179 | 2179 | generated by GNU Autoconf 2.69. Invocation command line was |
2180 | 2180 | |
2181 | 2181 | $ $0 $@ |
2556 | 2556 | |
2557 | 2557 | |
2558 | 2558 | |
2559 | PTEXENCVERSION=1.3.8/dev | |
2560 | ||
2561 | ||
2562 | PTEXENC_LT_VERSINFO=4:8:3 | |
2559 | PTEXENCVERSION=1.3.7 | |
2560 | ||
2561 | ||
2562 | PTEXENC_LT_VERSINFO=4:7:3 | |
2563 | 2563 | |
2564 | 2564 | |
2565 | 2565 | am__api_version='1.16' |
7868 | 7868 | |
7869 | 7869 | # Define the identity of the package. |
7870 | 7870 | PACKAGE='ptexenc' |
7871 | VERSION='1.3.8/dev' | |
7871 | VERSION='1.3.7' | |
7872 | 7872 | |
7873 | 7873 | |
7874 | 7874 | cat >>confdefs.h <<_ACEOF |
13886 | 13886 | Report bugs to <bug-libtool@gnu.org>." |
13887 | 13887 | |
13888 | 13888 | lt_cl_version="\ |
13889 | ptexenc config.lt 1.3.8/dev | |
13889 | ptexenc config.lt 1.3.7 | |
13890 | 13890 | configured by $0, generated by GNU Autoconf 2.69. |
13891 | 13891 | |
13892 | 13892 | Copyright (C) 2011 Free Software Foundation, Inc. |
15615 | 15615 | # report actual input values of CONFIG_FILES etc. instead of their |
15616 | 15616 | # values after options handling. |
15617 | 15617 | ac_log=" |
15618 | This file was extended by ptexenc $as_me 1.3.8/dev, which was | |
15618 | This file was extended by ptexenc $as_me 1.3.7, which was | |
15619 | 15619 | generated by GNU Autoconf 2.69. Invocation command line was |
15620 | 15620 | |
15621 | 15621 | CONFIG_FILES = $CONFIG_FILES |
15681 | 15681 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
15682 | 15682 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
15683 | 15683 | ac_cs_version="\\ |
15684 | ptexenc config.status 1.3.8/dev | |
15684 | ptexenc config.status 1.3.7 | |
15685 | 15685 | configured by $0, generated by GNU Autoconf 2.69, |
15686 | 15686 | with options \\"\$ac_cs_config\\" |
15687 | 15687 |
6 | 6 | dnl with or without modifications, as long as this notice is preserved. |
7 | 7 | dnl |
8 | 8 | dnl Keep package and shared library versions the same; |
9 | dnl see kpathsea/version.ac. | |
9 | dnl see kpathsea/vesion.ac. | |
10 | 10 | dnl |
11 | 11 | dnl This file is m4-included from configure.ac. |
12 | m4_define([ptexenc_version], [1.3.8/dev]) | |
12 | m4_define([ptexenc_version], [1.3.7]) |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for TeX Live Scripts 2020/dev. | |
2 | # Generated by GNU Autoconf 2.69 for TeX Live Scripts 2019. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-k@tug.org>. |
5 | 5 | # |
578 | 578 | # Identity of this package. |
579 | 579 | PACKAGE_NAME='TeX Live Scripts' |
580 | 580 | PACKAGE_TARNAME='tex-live-scripts' |
581 | PACKAGE_VERSION='2020/dev' | |
582 | PACKAGE_STRING='TeX Live Scripts 2020/dev' | |
581 | PACKAGE_VERSION='2019' | |
582 | PACKAGE_STRING='TeX Live Scripts 2019' | |
583 | 583 | PACKAGE_BUGREPORT='tex-k@tug.org' |
584 | 584 | PACKAGE_URL='' |
585 | 585 | |
1237 | 1237 | # Omit some internal or obsolete options to make the list less imposing. |
1238 | 1238 | # This message is too long to be a string in the A/UX 3.1 sh. |
1239 | 1239 | cat <<_ACEOF |
1240 | \`configure' configures TeX Live Scripts 2020/dev to adapt to many kinds of systems. | |
1240 | \`configure' configures TeX Live Scripts 2019 to adapt to many kinds of systems. | |
1241 | 1241 | |
1242 | 1242 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1243 | 1243 | |
1304 | 1304 | |
1305 | 1305 | if test -n "$ac_init_help"; then |
1306 | 1306 | case $ac_init_help in |
1307 | short | recursive ) echo "Configuration of TeX Live Scripts 2020/dev:";; | |
1307 | short | recursive ) echo "Configuration of TeX Live Scripts 2019:";; | |
1308 | 1308 | esac |
1309 | 1309 | cat <<\_ACEOF |
1310 | 1310 | |
1399 | 1399 | test -n "$ac_init_help" && exit $ac_status |
1400 | 1400 | if $ac_init_version; then |
1401 | 1401 | cat <<\_ACEOF |
1402 | TeX Live Scripts configure 2020/dev | |
1402 | TeX Live Scripts configure 2019 | |
1403 | 1403 | generated by GNU Autoconf 2.69 |
1404 | 1404 | |
1405 | 1405 | Copyright (C) 2012 Free Software Foundation, Inc. |
1454 | 1454 | This file contains any messages produced by compilers while |
1455 | 1455 | running configure, to aid debugging if configure makes a mistake. |
1456 | 1456 | |
1457 | It was created by TeX Live Scripts $as_me 2020/dev, which was | |
1457 | It was created by TeX Live Scripts $as_me 2019, which was | |
1458 | 1458 | generated by GNU Autoconf 2.69. Invocation command line was |
1459 | 1459 | |
1460 | 1460 | $ $0 $@ |
2321 | 2321 | |
2322 | 2322 | # Define the identity of the package. |
2323 | 2323 | PACKAGE='tex-live-scripts' |
2324 | VERSION='2020/dev' | |
2324 | VERSION='2019' | |
2325 | 2325 | |
2326 | 2326 | |
2327 | 2327 | cat >>confdefs.h <<_ACEOF |
4227 | 4227 | # report actual input values of CONFIG_FILES etc. instead of their |
4228 | 4228 | # values after options handling. |
4229 | 4229 | ac_log=" |
4230 | This file was extended by TeX Live Scripts $as_me 2020/dev, which was | |
4230 | This file was extended by TeX Live Scripts $as_me 2019, which was | |
4231 | 4231 | generated by GNU Autoconf 2.69. Invocation command line was |
4232 | 4232 | |
4233 | 4233 | CONFIG_FILES = $CONFIG_FILES |
4284 | 4284 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
4285 | 4285 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
4286 | 4286 | ac_cs_version="\\ |
4287 | TeX Live Scripts config.status 2020/dev | |
4287 | TeX Live Scripts config.status 2019 | |
4288 | 4288 | configured by $0, generated by GNU Autoconf 2.69, |
4289 | 4289 | with options \\"\$ac_cs_config\\" |
4290 | 4290 |
0 | 0 | #!/bin/sh |
1 | # Adapted from tlcockpit.sh to ensure the script works with cygwin | |
2 | 1 | |
3 | scriptname=`basename "$0" .sh` | |
4 | jar="$scriptname.jar" | |
5 | jarpath=`kpsewhich --progname="$scriptname" --format=texmfscripts "$jar"` | |
6 | ||
7 | kernel=`uname -s 2>/dev/null` | |
8 | if echo "$kernel" | grep CYGWIN >/dev/null; then | |
9 | CYGWIN_ROOT=`cygpath -w /` | |
10 | export CYGWIN_ROOT | |
11 | jarpath=`cygpath -w "$jarpath"` | |
2 | kernel=`uname -s` | |
3 | if test "${kernel#*CYGWIN}" != "$kernel" | |
4 | then | |
5 | jarpath=`cygpath -w $(kpsewhich --progname=convertgls2bib --format=texmfscripts convertgls2bib.jar)` | |
6 | else | |
7 | jarpath=`kpsewhich --progname=convertgls2bib --format=texmfscripts convertgls2bib.jar` | |
12 | 8 | fi |
13 | 9 | |
14 | exec java -jar "$jarpath" "$@" | |
10 | java -jar "$jarpath" "$@" | |
11 |
343 | 343 | if os.type == "windows" then |
344 | 344 | package.preload["texrunner.shellutil"] = function(...) |
345 | 345 | --[[ |
346 | Copyright 2016,2019 ARATA Mizuki | |
346 | Copyright 2016 ARATA Mizuki | |
347 | 347 | |
348 | 348 | This file is part of ClutTeX. |
349 | 349 | |
362 | 362 | ]] |
363 | 363 | |
364 | 364 | local string_gsub = string.gsub |
365 | local os_execute = os.execute | |
366 | 365 | |
367 | 366 | -- s: string |
368 | 367 | local function escape(s) |
370 | 369 | end |
371 | 370 | |
372 | 371 | |
373 | local function has_command(name) | |
374 | local result = os_execute("where " .. escape(name) .. " > NUL 2>&1") | |
375 | -- Note that os.execute returns a number on Lua 5.1 or LuaTeX | |
376 | return result == 0 or result == true | |
377 | end | |
378 | ||
379 | 372 | return { |
380 | 373 | escape = escape, |
381 | has_command = has_command, | |
382 | 374 | } |
383 | 375 | end |
384 | 376 | else |
385 | 377 | package.preload["texrunner.shellutil"] = function(...) |
386 | 378 | --[[ |
387 | Copyright 2016,2019 ARATA Mizuki | |
379 | Copyright 2016 ARATA Mizuki | |
388 | 380 | |
389 | 381 | This file is part of ClutTeX. |
390 | 382 | |
407 | 399 | local table = table |
408 | 400 | local table_insert = table.insert |
409 | 401 | local table_concat = table.concat |
410 | local os_execute = os.execute | |
411 | 402 | |
412 | 403 | -- s: string |
413 | 404 | local function escape(s) |
438 | 429 | end |
439 | 430 | |
440 | 431 | |
441 | local function has_command(name) | |
442 | local result = os_execute("which " .. escape(name) .. " > /dev/null") | |
443 | -- Note that os.execute returns a number on Lua 5.1 or LuaTeX | |
444 | return result == 0 or result == true | |
445 | end | |
446 | ||
447 | 432 | return { |
448 | 433 | escape = escape, |
449 | has_command = has_command, | |
450 | 434 | } |
451 | 435 | end |
452 | 436 | end |
557 | 541 | |
558 | 542 | -- options_and_params, i = parseoption(arg, options) |
559 | 543 | -- options[i] = {short = "o", long = "option" [, param = true] [, boolean = true] [, allow_single_hyphen = false]} |
560 | -- options_and_params[j] = {"option", "value"} | |
561 | 544 | -- arg[i], arg[i + 1], ..., arg[#arg] are non-options |
562 | 545 | local function parseoption(arg, options) |
563 | 546 | local i = 1 |
597 | 580 | elseif o.boolean and name == "no-" .. o.long then |
598 | 581 | -- --no-option |
599 | 582 | opt = o |
600 | param = false | |
601 | 583 | break |
602 | 584 | end |
603 | 585 | end |
637 | 619 | elseif o.boolean and name == "no-" .. o.long then |
638 | 620 | -- -no-option |
639 | 621 | opt = o |
640 | param = false | |
641 | 622 | break |
642 | 623 | end |
643 | 624 | elseif o.long and #name >= 2 and (o.long == name or (o.boolean and name == "no-" .. o.long)) then |
2142 | 2123 | info = info_msg, |
2143 | 2124 | } |
2144 | 2125 | end |
2145 | package.preload["texrunner.fswatcher_windows"] = function(...) | |
2146 | 2126 | --[[ |
2147 | Copyright 2019 ARATA Mizuki | |
2127 | Copyright 2016,2018-2019 ARATA Mizuki | |
2148 | 2128 | |
2149 | 2129 | This file is part of ClutTeX. |
2150 | 2130 | |
2162 | 2142 | along with ClutTeX. If not, see <http://www.gnu.org/licenses/>. |
2163 | 2143 | ]] |
2164 | 2144 | |
2165 | local ffi = require "ffi" | |
2166 | local bitlib = assert(bit32 or bit, "Neither bit32 (Lua 5.2) nor bit (LuaJIT) found") -- Lua 5.2 or LuaJIT | |
2167 | ||
2168 | ffi.cdef[[ | |
2169 | typedef int BOOL; | |
2170 | typedef unsigned int UINT; | |
2171 | typedef uint32_t DWORD; | |
2172 | typedef void *HANDLE; | |
2173 | typedef uintptr_t ULONG_PTR; | |
2174 | typedef uint16_t WCHAR; | |
2175 | typedef struct _OVERLAPPED { | |
2176 | ULONG_PTR Internal; | |
2177 | ULONG_PTR InternalHigh; | |
2178 | union { | |
2179 | struct { | |
2180 | DWORD Offset; | |
2181 | DWORD OffsetHigh; | |
2182 | }; | |
2183 | void *Pointer; | |
2184 | }; | |
2185 | HANDLE hEvent; | |
2186 | } OVERLAPPED; | |
2187 | typedef struct _FILE_NOTIFY_INFORMATION { | |
2188 | DWORD NextEntryOffset; | |
2189 | DWORD Action; | |
2190 | DWORD FileNameLength; | |
2191 | WCHAR FileName[?]; | |
2192 | } FILE_NOTIFY_INFORMATION; | |
2193 | typedef void (__stdcall *LPOVERLAPPED_COMPLETION_ROUTINE)(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, OVERLAPPED *lpOverlapped); | |
2194 | DWORD GetLastError(); | |
2195 | BOOL CloseHandle(HANDLE hObject); | |
2196 | HANDLE CreateFileA(const char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, void *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); | |
2197 | HANDLE CreateIoCompletionPort(HANDLE fileHandle, HANDLE existingCompletionPort, ULONG_PTR completionKey, DWORD numberOfConcurrentThreads); | |
2198 | BOOL ReadDirectoryChangesW(HANDLE hDirectory, void *lpBuffer, DWORD nBufferLength, BOOL bWatchSubtree, DWORD dwNotifyFilter, DWORD *lpBytesReturned, OVERLAPPED *lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpOverlappedCompletionRoutine); | |
2199 | BOOL GetQueuedCompletionStatus(HANDLE CompletionPort, DWORD *lpNumberOfBytes, ULONG_PTR *lpCompletionKey, OVERLAPPED **lpOverlapped, DWORD dwMilliseconds); | |
2200 | int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, const char *lpMultiByteStr, int cbMultiByte, WCHAR *lpWideCharStr, int cchWideChar); | |
2201 | int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, const WCHAR *lpWideCharStr, int cchWideChar, char *lpMultiByteStr, int cbMultiByte, const char *lpDefaultChar, BOOL *lpUsedDefaultChar); | |
2202 | DWORD GetFullPathNameA(const char *lpFileName, DWORD nBufferLength, char *lpBuffer, char **lpFilePart); | |
2203 | uint64_t GetTickCount64(); | |
2204 | ]] | |
2205 | ||
2206 | -- LuaTeX's FFI does not equate a null pointer with nil. | |
2207 | -- On LuaJIT, ffi.NULL is just nil. | |
2208 | local NULL = ffi.NULL | |
2209 | ||
2210 | -- GetLastError | |
2211 | local ERROR_FILE_NOT_FOUND = 0x0002 | |
2212 | local ERROR_PATH_NOT_FOUND = 0x0003 | |
2213 | local ERROR_ACCESS_DENIED = 0x0005 | |
2214 | local ERROR_INVALID_PARAMETER = 0x0057 | |
2215 | local ERROR_INSUFFICIENT_BUFFER = 0x007A | |
2216 | local WAIT_TIMEOUT = 0x0102 | |
2217 | local ERROR_ABANDONED_WAIT_0 = 0x02DF | |
2218 | local ERROR_NOACCESS = 0x03E6 | |
2219 | local ERROR_INVALID_FLAGS = 0x03EC | |
2220 | local ERROR_NOTIFY_ENUM_DIR = 0x03FE | |
2221 | local ERROR_NO_UNICODE_TRANSLATION = 0x0459 | |
2222 | local KnownErrors = { | |
2223 | [ERROR_FILE_NOT_FOUND] = "ERROR_FILE_NOT_FOUND", | |
2224 | [ERROR_PATH_NOT_FOUND] = "ERROR_PATH_NOT_FOUND", | |
2225 | [ERROR_ACCESS_DENIED] = "ERROR_ACCESS_DENIED", | |
2226 | [ERROR_INVALID_PARAMETER] = "ERROR_INVALID_PARAMETER", | |
2227 | [ERROR_INSUFFICIENT_BUFFER] = "ERROR_INSUFFICIENT_BUFFER", | |
2228 | [ERROR_ABANDONED_WAIT_0] = "ERROR_ABANDONED_WAIT_0", | |
2229 | [ERROR_NOACCESS] = "ERROR_NOACCESS", | |
2230 | [ERROR_INVALID_FLAGS] = "ERROR_INVALID_FLAGS", | |
2231 | [ERROR_NOTIFY_ENUM_DIR] = "ERROR_NOTIFY_ENUM_DIR", | |
2232 | [ERROR_NO_UNICODE_TRANSLATION] = "ERROR_NO_UNICODE_TRANSLATION", | |
2233 | } | |
2234 | ||
2235 | -- CreateFile | |
2236 | local FILE_FLAG_BACKUP_SEMANTICS = 0x02000000 | |
2237 | local FILE_FLAG_OVERLAPPED = 0x40000000 | |
2238 | local OPEN_EXISTING = 3 | |
2239 | local FILE_SHARE_READ = 0x00000001 | |
2240 | local FILE_SHARE_WRITE = 0x00000002 | |
2241 | local FILE_SHARE_DELETE = 0x00000004 | |
2242 | local FILE_LIST_DIRECTORY = 0x1 | |
2243 | local INVALID_HANDLE_VALUE = ffi.cast("void *", -1) | |
2244 | ||
2245 | -- ReadDirectoryChangesW / FILE_NOTIFY_INFORMATION | |
2246 | local FILE_NOTIFY_CHANGE_FILE_NAME = 0x00000001 | |
2247 | local FILE_NOTIFY_CHANGE_DIR_NAME = 0x00000002 | |
2248 | local FILE_NOTIFY_CHANGE_ATTRIBUTES = 0x00000004 | |
2249 | local FILE_NOTIFY_CHANGE_SIZE = 0x00000008 | |
2250 | local FILE_NOTIFY_CHANGE_LAST_WRITE = 0x00000010 | |
2251 | local FILE_NOTIFY_CHANGE_LAST_ACCESS = 0x00000020 | |
2252 | local FILE_NOTIFY_CHANGE_CREATION = 0x00000040 | |
2253 | local FILE_NOTIFY_CHANGE_SECURITY = 0x00000100 | |
2254 | local FILE_ACTION_ADDED = 0x00000001 | |
2255 | local FILE_ACTION_REMOVED = 0x00000002 | |
2256 | local FILE_ACTION_MODIFIED = 0x00000003 | |
2257 | local FILE_ACTION_RENAMED_OLD_NAME = 0x00000004 | |
2258 | local FILE_ACTION_RENAMED_NEW_NAME = 0x00000005 | |
2259 | ||
2260 | -- WideCharToMultiByte / MultiByteToWideChar | |
2261 | local CP_ACP = 0 | |
2262 | local CP_UTF8 = 65001 | |
2263 | ||
2264 | local C = ffi.C | |
2265 | ||
2266 | local function format_error(name, lasterror, extra) | |
2267 | local errorname = KnownErrors[lasterror] or string.format("error code %d", lasterror) | |
2268 | if extra then | |
2269 | return string.format("%s failed with %s (0x%04x) [%s]", name, errorname, lasterror, extra) | |
2270 | else | |
2271 | return string.format("%s failed with %s (0x%04x)", name, errorname, lasterror) | |
2272 | end | |
2273 | end | |
2274 | local function wcs_to_mbs(wstr, wstrlen, codepage) | |
2275 | -- wstr: FFI uint16_t[?] | |
2276 | -- wstrlen: length of wstr, or -1 if NUL-terminated | |
2277 | if wstrlen == 0 then | |
2278 | return "" | |
2279 | end | |
2280 | codepage = codepage or CP_ACP | |
2281 | local dwFlags = 0 | |
2282 | local result = C.WideCharToMultiByte(codepage, dwFlags, wstr, wstrlen, nil, 0, nil, nil) | |
2283 | if result <= 0 then | |
2284 | -- Failed | |
2285 | local lasterror = C.GetLastError() | |
2286 | -- Candidates: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER, ERROR_NO_UNICODE_TRANSLATION | |
2287 | return nil, format_error("WideCharToMultiByte", lasterror) | |
2288 | end | |
2289 | local mbsbuf = ffi.new("char[?]", result) | |
2290 | result = C.WideCharToMultiByte(codepage, dwFlags, wstr, wstrlen, mbsbuf, result, nil, nil) | |
2291 | if result <= 0 then | |
2292 | -- Failed | |
2293 | local lasterror = C.GetLastError() | |
2294 | -- Candidates: ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER, ERROR_NO_UNICODE_TRANSLATION | |
2295 | return nil, format_error("WideCharToMultiByte", lasterror) | |
2296 | end | |
2297 | return ffi.string(mbsbuf, result) | |
2298 | end | |
2299 | local function mbs_to_wcs(str, codepage) | |
2300 | -- str: Lua string | |
2301 | if str == "" then | |
2302 | return ffi.new("WCHAR[0]") | |
2303 | end | |
2304 | codepage = codepage or CP_ACP | |
2305 | local dwFlags = 0 | |
2306 | local result = C.MultiByteToWideChar(codepage, dwFlags, str, #str, nil, 0) | |
2307 | if result <= 0 then | |
2308 | local lasterror = C.GetLastError() | |
2309 | -- ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER, ERROR_NO_UNICODE_TRANSLATION | |
2310 | return nil, format_error("MultiByteToWideChar", lasterror) | |
2311 | end | |
2312 | local wcsbuf = ffi.new("WCHAR[?]", result) | |
2313 | result = C.MultiByteToWideChar(codepage, dwFlags, str, #str, wcsbuf, result) | |
2314 | if result <= 0 then | |
2315 | local lasterror = C.GetLastError() | |
2316 | return nil, format_error("MultiByteToWideChar", lasterror) | |
2317 | end | |
2318 | return wcsbuf, result | |
2319 | end | |
2320 | ||
2321 | ||
2322 | local function get_full_path_name(filename) | |
2323 | local bufsize = 1024 | |
2324 | local buffer | |
2325 | local filePartPtr = ffi.new("char*[1]") | |
2326 | local result | |
2327 | repeat | |
2328 | buffer = ffi.new("char[?]", bufsize) | |
2329 | result = C.GetFullPathNameA(filename, bufsize, buffer, filePartPtr) | |
2330 | if result == 0 then | |
2331 | local lasterror = C.GetLastError() | |
2332 | return nil, format_error("GetFullPathNameA", lasterror, filename) | |
2333 | elseif bufsize < result then | |
2334 | -- result: buffer size required to hold the path + terminating NUL | |
2335 | bufsize = result | |
2336 | end | |
2337 | until result < bufsize | |
2338 | local fullpath = ffi.string(buffer, result) | |
2339 | local filePart = ffi.string(filePartPtr[0]) | |
2340 | local dirPart = ffi.string(buffer, ffi.cast("intptr_t", filePartPtr[0]) - ffi.cast("intptr_t", buffer)) -- LuaTeX's FFI doesn't support pointer subtraction | |
2341 | return fullpath, filePart, dirPart | |
2342 | end | |
2343 | ||
2344 | --[[ | |
2345 | dirwatche.dirname : string | |
2346 | dirwatcher._rawhandle : cdata HANDLE | |
2347 | dirwatcher._overlapped : cdata OVERLAPPED | |
2348 | dirwatcher._buffer : cdata char[?] | |
2349 | ]] | |
2350 | local dirwatcher_meta = {} | |
2351 | dirwatcher_meta.__index = dirwatcher_meta | |
2352 | function dirwatcher_meta:close() | |
2353 | if self._rawhandle ~= nil then | |
2354 | C.CloseHandle(ffi.gc(self._rawhandle, nil)) | |
2355 | self._rawhandle = nil | |
2356 | end | |
2357 | end | |
2358 | local function open_directory(dirname) | |
2359 | local dwShareMode = bitlib.bor(FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE) | |
2360 | local dwFlagsAndAttributes = bitlib.bor(FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OVERLAPPED) | |
2361 | local handle = C.CreateFileA(dirname, FILE_LIST_DIRECTORY, dwShareMode, nil, OPEN_EXISTING, dwFlagsAndAttributes, nil) | |
2362 | if handle == INVALID_HANDLE_VALUE then | |
2363 | local lasterror = C.GetLastError() | |
2364 | print("Failed to open "..dirname) | |
2365 | return nil, format_error("CreateFileA", lasterror, dirname) | |
2366 | end | |
2367 | return setmetatable({ | |
2368 | dirname = dirname, | |
2369 | _rawhandle = ffi.gc(handle, C.CloseHandle), | |
2370 | _overlapped = ffi.new("OVERLAPPED"), | |
2371 | _buffer = ffi.new("char[?]", 1024), | |
2372 | }, dirwatcher_meta) | |
2373 | end | |
2374 | function dirwatcher_meta:start_watch(watchSubtree) | |
2375 | local dwNotifyFilter = bitlib.bor(FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_NOTIFY_CHANGE_SIZE, FILE_NOTIFY_CHANGE_LAST_WRITE, FILE_NOTIFY_CHANGE_LAST_ACCESS, FILE_NOTIFY_CHANGE_CREATION, FILE_NOTIFY_CHANGE_SECURITY) | |
2376 | local buffer = self._buffer | |
2377 | local bufferSize = ffi.sizeof(buffer) | |
2378 | local result = C.ReadDirectoryChangesW(self._rawhandle, buffer, bufferSize, watchSubtree, dwNotifyFilter, nil, self._overlapped, nil) | |
2379 | if result == 0 then | |
2380 | local lasterror = C.GetLastError() | |
2381 | return nil, format_error("ReadDirectoryChangesW", lasterror, self.dirname) | |
2382 | end | |
2383 | return true | |
2384 | end | |
2385 | local ActionTable = { | |
2386 | [FILE_ACTION_ADDED] = "added", | |
2387 | [FILE_ACTION_REMOVED] = "removed", | |
2388 | [FILE_ACTION_MODIFIED] = "modified", | |
2389 | [FILE_ACTION_RENAMED_OLD_NAME] = "rename_from", | |
2390 | [FILE_ACTION_RENAMED_NEW_NAME] = "rename_to", | |
2391 | } | |
2392 | function dirwatcher_meta:process(numberOfBytes) | |
2393 | -- self._buffer received `numberOfBytes` bytes | |
2394 | local buffer = self._buffer | |
2395 | numberOfBytes = math.min(numberOfBytes, ffi.sizeof(buffer)) | |
2396 | local ptr = ffi.cast("char *", buffer) | |
2397 | local structSize = ffi.sizeof("FILE_NOTIFY_INFORMATION", 1) | |
2398 | local t = {} | |
2399 | while numberOfBytes >= structSize do | |
2400 | local notifyInfo = ffi.cast("FILE_NOTIFY_INFORMATION*", ptr) | |
2401 | local nextEntryOffset = notifyInfo.NextEntryOffset | |
2402 | local action = notifyInfo.Action | |
2403 | local fileNameLength = notifyInfo.FileNameLength | |
2404 | local fileName = notifyInfo.FileName | |
2405 | local u = { action = ActionTable[action], filename = wcs_to_mbs(fileName, fileNameLength / 2) } | |
2406 | table.insert(t, u) | |
2407 | if nextEntryOffset == 0 or numberOfBytes <= nextEntryOffset then | |
2408 | break | |
2409 | end | |
2410 | numberOfBytes = numberOfBytes - nextEntryOffset | |
2411 | ptr = ptr + nextEntryOffset | |
2412 | end | |
2413 | return t | |
2414 | end | |
2415 | ||
2416 | --[[ | |
2417 | watcher._rawport : cdata HANDLE | |
2418 | watcher._pending : array of { | |
2419 | action = ..., filename = ... | |
2420 | } | |
2421 | watcher._directories[dirname] = { | |
2422 | dir = directory watcher, | |
2423 | dirname = dirname, | |
2424 | files = { [filename] = user-supplied path } -- files to watch | |
2425 | } | |
2426 | watcher[i] = i-th directory (_directories[dirname] for some dirname) | |
2427 | ]] | |
2428 | ||
2429 | local fswatcher_meta = {} | |
2430 | fswatcher_meta.__index = fswatcher_meta | |
2431 | local function new_watcher() | |
2432 | local port = C.CreateIoCompletionPort(INVALID_HANDLE_VALUE, nil, 0, 0) | |
2433 | if port == NULL then | |
2434 | local lasterror = C.GetLastError() | |
2435 | return nil, format_error("CreateIoCompletionPort", lasterror) | |
2436 | end | |
2437 | return setmetatable({ | |
2438 | _rawport = ffi.gc(port, C.CloseHandle), -- ? | |
2439 | _pending = {}, | |
2440 | _directories = {}, | |
2441 | }, fswatcher_meta) | |
2442 | end | |
2443 | local function add_directory(self, dirname) | |
2444 | local t = self._directories[dirname] | |
2445 | if not t then | |
2446 | local dirwatcher, err = open_directory(dirname) | |
2447 | if not dirwatcher then | |
2448 | return dirwatcher, err | |
2449 | end | |
2450 | t = { dirwatcher = dirwatcher, dirname = dirname, files = {} } | |
2451 | table.insert(self, t) | |
2452 | local i = #self | |
2453 | local result = C.CreateIoCompletionPort(dirwatcher._rawhandle, self._rawport, i, 0) | |
2454 | if result == NULL then | |
2455 | local lasterror = C.GetLastError() | |
2456 | return nil, format_error("CreateIoCompletionPort", lasterror, dirname) | |
2457 | end | |
2458 | self._directories[dirname] = t | |
2459 | local result, err = dirwatcher:start_watch(false) | |
2460 | if not result then | |
2461 | return result, err | |
2462 | end | |
2463 | end | |
2464 | return t | |
2465 | end | |
2466 | function fswatcher_meta:add_file(path, ...) | |
2467 | local fullpath, filename, dirname = get_full_path_name(path) | |
2468 | local t, err = add_directory(self, dirname) | |
2469 | if not t then | |
2470 | return t, err | |
2471 | end | |
2472 | t.files[filename] = path | |
2473 | return true | |
2474 | end | |
2475 | local INFINITE = 0xFFFFFFFF | |
2476 | local function get_queued(self, timeout) | |
2477 | local startTime = C.GetTickCount64() | |
2478 | local timeout_ms | |
2479 | if timeout == nil then | |
2480 | timeout_ms = INFINITE | |
2481 | else | |
2482 | timeout_ms = timeout * 1000 | |
2483 | end | |
2484 | local numberOfBytesPtr = ffi.new("DWORD[1]") | |
2485 | local completionKeyPtr = ffi.new("ULONG_PTR[1]") | |
2486 | local lpOverlapped = ffi.new("OVERLAPPED*[1]") | |
2487 | repeat | |
2488 | local result = C.GetQueuedCompletionStatus(self._rawport, numberOfBytesPtr, completionKeyPtr, lpOverlapped, timeout_ms) | |
2489 | if result == 0 then | |
2490 | local lasterror = C.GetLastError() | |
2491 | if lasterror == WAIT_TIMEOUT then | |
2492 | return nil, "timeout" | |
2493 | else | |
2494 | return nil, format_error("GetQueuedCompletionStatus", lasterror) | |
2495 | end | |
2496 | end | |
2497 | local numberOfBytes = numberOfBytesPtr[0] | |
2498 | local completionKey = tonumber(completionKeyPtr[0]) | |
2499 | local dir_t = assert(self[completionKey], "invalid completion key: " .. tostring(completionKey)) | |
2500 | local t = dir_t.dirwatcher:process(numberOfBytes) | |
2501 | dir_t.dirwatcher:start_watch(false) | |
2502 | local found = false | |
2503 | for i,v in ipairs(t) do | |
2504 | local path = dir_t.files[v.filename] | |
2505 | if path then | |
2506 | found = true | |
2507 | table.insert(self._pending, {path = path, action = v.action}) | |
2508 | end | |
2509 | end | |
2510 | if found then | |
2511 | return true | |
2512 | end | |
2513 | if timeout_ms ~= INFINITE then | |
2514 | local tt = C.GetTickCount64() | |
2515 | timeout_ms = timeout_ms - (tt - startTime) | |
2516 | startTime = tt | |
2517 | end | |
2518 | until timeout_ms < 0 | |
2519 | return nil, "timeout" | |
2520 | end | |
2521 | function fswatcher_meta:next(timeout) | |
2522 | if #self._pending > 0 then | |
2523 | local result = table.remove(self._pending, 1) | |
2524 | get_queued(self, 0) -- ignore error | |
2525 | return result | |
2526 | else | |
2527 | local result, err = get_queued(self, timeout) | |
2528 | if result == nil then | |
2529 | return nil, err | |
2530 | end | |
2531 | return table.remove(self._pending, 1) | |
2532 | end | |
2533 | end | |
2534 | function fswatcher_meta:close() | |
2535 | if self._rawport ~= nil then | |
2536 | for i,v in ipairs(self) do | |
2537 | v.dirwatcher:close() | |
2538 | end | |
2539 | C.CloseHandle(ffi.gc(self._rawport, nil)) | |
2540 | self._rawport = nil | |
2541 | end | |
2542 | end | |
2543 | --[[ | |
2544 | local watcher = require("fswatcher_windows").new() | |
2545 | assert(watcher:add_file("rdc-sync.c")) | |
2546 | assert(watcher:add_file("sub2/hoge")) | |
2547 | for i = 1, 10 do | |
2548 | local result, err = watcher:next(2) | |
2549 | if err == "timeout" then | |
2550 | print(os.date(), "timeout") | |
2551 | else | |
2552 | assert(result, err) | |
2553 | print(os.date(), result.path, result.action) | |
2554 | end | |
2555 | end | |
2556 | watcher:close() | |
2557 | ]] | |
2558 | return { | |
2559 | new = new_watcher, | |
2560 | } | |
2561 | end | |
2562 | --[[ | |
2563 | Copyright 2016,2018-2019 ARATA Mizuki | |
2564 | ||
2565 | This file is part of ClutTeX. | |
2566 | ||
2567 | ClutTeX is free software: you can redistribute it and/or modify | |
2568 | it under the terms of the GNU General Public License as published by | |
2569 | the Free Software Foundation, either version 3 of the License, or | |
2570 | (at your option) any later version. | |
2571 | ||
2572 | ClutTeX is distributed in the hope that it will be useful, | |
2573 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
2574 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
2575 | GNU General Public License for more details. | |
2576 | ||
2577 | You should have received a copy of the GNU General Public License | |
2578 | along with ClutTeX. If not, see <http://www.gnu.org/licenses/>. | |
2579 | ]] | |
2580 | ||
2581 | CLUTTEX_VERSION = "v0.3" | |
2145 | CLUTTEX_VERSION = "v0.2" | |
2582 | 2146 | |
2583 | 2147 | -- Standard libraries |
2584 | 2148 | local coroutine = coroutine |
2599 | 2163 | local message = require "texrunner.message" |
2600 | 2164 | local extract_bibtex_from_aux_file = require "texrunner.auxfile".extract_bibtex_from_aux_file |
2601 | 2165 | local handle_cluttex_options = require "texrunner.handleoption".handle_cluttex_options |
2602 | ||
2603 | os.setlocale("", "ctype") -- Workaround for recent Universal CRT | |
2604 | 2166 | |
2605 | 2167 | -- arguments: input file name, jobname, etc... |
2606 | 2168 | local function genOutputDirectory(...) |
3048 | 2610 | if options.watch then |
3049 | 2611 | -- Watch mode |
3050 | 2612 | local success, status = do_typeset() |
3051 | -- TODO: filenames here can be UTF-8 if command_line_encoding=utf-8 | |
3052 | 2613 | local filelist, filemap = reruncheck.parse_recorder_file(recorderfile, options) |
3053 | 2614 | if engine.is_luatex and fsutil.isfile(recorderfile2) then |
3054 | 2615 | filelist, filemap = reruncheck.parse_recorder_file(recorderfile2, options, filelist, filemap) |
3059 | 2620 | table.insert(input_files_to_watch, fileinfo.abspath) |
3060 | 2621 | end |
3061 | 2622 | end |
3062 | local fswatcherlib | |
3063 | if os.type == "windows" then | |
3064 | -- Windows: Try built-in filesystem watcher | |
3065 | local succ, result = pcall(require, "texrunner.fswatcher_windows") | |
3066 | if not succ and CLUTTEX_VERBOSITY >= 1 then | |
3067 | message.warn("Failed to load texrunner.fswatcher_windows: " .. result) | |
3068 | end | |
3069 | fswatcherlib = result | |
3070 | end | |
3071 | if fswatcherlib then | |
3072 | if CLUTTEX_VERBOSITY >= 2 then | |
3073 | message.info("Using built-in filesystem watcher for Windows") | |
3074 | end | |
3075 | local watcher = assert(fswatcherlib.new()) | |
2623 | local fswatch_command = {"fswatch", "--event=Updated", "--"} | |
2624 | for _,path in ipairs(input_files_to_watch) do | |
2625 | table.insert(fswatch_command, shellutil.escape(path)) | |
2626 | end | |
2627 | if CLUTTEX_VERBOSITY >= 1 then | |
2628 | message.exec(table.concat(fswatch_command, " ")) | |
2629 | end | |
2630 | local fswatch = assert(io.popen(table.concat(fswatch_command, " "), "r")) | |
2631 | for l in fswatch:lines() do | |
2632 | local found = false | |
3076 | 2633 | for _,path in ipairs(input_files_to_watch) do |
3077 | assert(watcher:add_file(path)) | |
3078 | end | |
3079 | while true do | |
3080 | local result = assert(watcher:next()) | |
3081 | if CLUTTEX_VERBOSITY >= 2 then | |
3082 | message.info(string.format("%s %s"), result.action, result.path) | |
3083 | end | |
2634 | if l == path then | |
2635 | found = true | |
2636 | break | |
2637 | end | |
2638 | end | |
2639 | if found then | |
3084 | 2640 | local success, status = do_typeset() |
3085 | 2641 | if not success then |
3086 | 2642 | -- Not successful |
3087 | 2643 | end |
3088 | 2644 | end |
3089 | elseif shellutil.has_command("fswatch") then | |
3090 | local fswatch_command = {"fswatch", "--event=Updated", "--"} | |
3091 | for _,path in ipairs(input_files_to_watch) do | |
3092 | table.insert(fswatch_command, shellutil.escape(path)) | |
3093 | end | |
3094 | local fswatch_command_str = table.concat(fswatch_command, " ") | |
3095 | if CLUTTEX_VERBOSITY >= 1 then | |
3096 | message.exec(fswatch_command_str) | |
3097 | end | |
3098 | local fswatch = assert(io.popen(fswatch_command_str, "r")) | |
3099 | for l in fswatch:lines() do | |
3100 | local found = false | |
3101 | for _,path in ipairs(input_files_to_watch) do | |
3102 | if l == path then | |
3103 | found = true | |
3104 | break | |
3105 | end | |
3106 | end | |
3107 | if found then | |
3108 | local success, status = do_typeset() | |
3109 | if not success then | |
3110 | -- Not successful | |
3111 | end | |
3112 | end | |
3113 | end | |
3114 | elseif shellutil.has_command("inotifywait") then | |
3115 | local inotifywait_command = {"inotifywait", "--monitor", "--event=modify", "--event=attrib", "--format=%w", "--quiet"} | |
3116 | for _,path in ipairs(input_files_to_watch) do | |
3117 | table.insert(inotifywait_command, shellutil.escape(path)) | |
3118 | end | |
3119 | local inotifywait_command_str = table.concat(inotifywait_command, " ") | |
3120 | if CLUTTEX_VERBOSITY >= 1 then | |
3121 | message.exec(inotifywait_command_str) | |
3122 | end | |
3123 | local inotifywait = assert(io.popen(inotifywait_command_str, "r")) | |
3124 | for l in inotifywait:lines() do | |
3125 | local found = false | |
3126 | for _,path in ipairs(input_files_to_watch) do | |
3127 | if l == path then | |
3128 | found = true | |
3129 | break | |
3130 | end | |
3131 | end | |
3132 | if found then | |
3133 | local success, status = do_typeset() | |
3134 | if not success then | |
3135 | -- Not successful | |
3136 | end | |
3137 | end | |
3138 | end | |
3139 | else | |
3140 | message.error("Could not watch files because neither `fswatch' nor `inotifywait' was installed.") | |
3141 | message.info("See ClutTeX's manual for details.") | |
3142 | os.exit(1) | |
3143 | 2645 | end |
3144 | 2646 | |
3145 | 2647 | else |
26 | 26 | ]]) |
27 | 27 | os.exit(1) |
28 | 28 | elseif arg[1]=="--version" or arg[1]=="-v" then |
29 | print "ctanbib version v0.1c" | |
29 | print "ctanbib version v0.1b" | |
30 | 30 | os.exit(1) |
31 | 31 | elseif arg[1]=="--ctan" or arg[1]=="-c" then |
32 | 32 | table.remove(arg, 1) |
55 | 55 | |
56 | 56 | |
57 | 57 | local load_xml = function(url) |
58 | -- local command = io.popen("wget -qO- ".. url,"r") | |
59 | local command = io.popen("curl -sS ".. url,"r") | |
58 | local command = io.popen("wget -qO- ".. url,"r") | |
60 | 59 | |
61 | 60 | local info = command:read("*all") |
62 | 61 | command:close() |
37 | 37 | use File::Spec (); |
38 | 38 | use Getopt::Long (); |
39 | 39 | use Pod::Usage (); |
40 | use POSIX (); | |
41 | 40 | |
42 | 41 | my ($d, $m, $y) = (localtime time)[3 .. 5]; |
43 | 42 | my $TODAY = sprintf "%04d/%02d/%02d", $y + 1900, $m + 1, $d; |
66 | 65 | |
67 | 66 | =begin Comment |
68 | 67 | |
69 | LaTeX's NFSS contains a limited number of standard codes for weight and width: | |
68 | Latex's NFSS contains a limited number of standard codes for weight and width: | |
70 | 69 | - weight: ul, el, l, sl, m, sb, b, eb, ub |
71 | 70 | - width: uc, ec, c, sc, m, sx, x, ex, ux |
72 | 71 | |
82 | 81 | 2. We add "ssub" rules to the .fd files that map the standard NFSS codes |
83 | 82 | to actual fonts. |
84 | 83 | |
85 | In step 1, we follow NFSS in leaving out any occurrence of | |
86 | the word "regular" unless *both* weight and width are Regular; | |
87 | in that case, the 'series' attribute becomes "regular". | |
88 | ||
89 | The two tables NFSS_WEIGHT and NFSS_WIDTH are used to control step 2. | |
84 | In step 1, we follow NFSS in leaving out any occurrence of the word "regular" | |
85 | unless *both* weight and width are Regular; in that case, the series attribute | |
86 | becomes "regular". | |
87 | ||
88 | The two tables %NFSS_WEIGHT and %NFSS_WIDTH are used to control step 2. | |
90 | 89 | It contains several entries of the form |
91 | 90 | |
92 | 91 | sc => [ qw( semicondensed narrow ) ], |
93 | 92 | |
94 | 93 | This should be read as follows: the NFSS code "sc" is mapped to the *first* |
95 | 94 | width on the right hand side that is present in the current font family. |
95 | ||
96 | Given the lack of a standardised font naming scheme, this mapping system | |
97 | will probably leave some fonts without matching NFSS codes and, vice versa, | |
98 | some NFSS codes without matching font. It is, however, probably the best | |
99 | that can be done in an automated way. If you think you can do better, | |
100 | I welcome pull requests :-) | |
96 | 101 | |
97 | 102 | Please note that the tables contain empty keys instead of "m" for |
98 | 103 | the regular weight and width. NFSS actually combines weight and width |
106 | 111 | to be searched for. |
107 | 112 | |
108 | 113 | These tables can be extended to teach autoinst about new weights or widths. |
109 | Suppose your font family contains a "Hemibold" weight. Then add the name | |
110 | "hemibold" to the right hand side of the "sb" entry in the NFSS_WEIGHT | |
114 | Suppose your font family contains a "Hemibold" weight. Then simply add the name | |
115 | "hemibold" to the right hand side of the "sb" entry in the %NFSS_WEIGHT | |
111 | 116 | table: |
112 | 117 | |
113 | 118 | sb => [ qw( semibold demi demibold medium hemibold ) ], |
118 | 123 | NFSS code). |
119 | 124 | |
120 | 125 | Note that autoinst converts all metadata to lowercase to avoid inconsistent |
121 | capitalization; so all entries in these tables should be *lowercase* as well. | |
122 | ||
123 | Technical note: | |
124 | We define NFSS_WEIGHT and NFSS_WIDTH first as arrays and then as hashtables; | |
125 | this allows us to use the array-variants as an *ordered* list of keys. | |
126 | capitalization; hence all entries in these tables should be *lowercase* as well. | |
126 | 127 | |
127 | 128 | |
128 | 129 | Finally, some random remarks about these tables: |
134 | 135 | mostly, however, it is a very light weight below Ultralight. |
135 | 136 | - Semilight weights are virtually nonexistent, except for Thesis |
136 | 137 | (which contains a Semilight weight) and Arnhem (which has Blond). |
137 | - Book is usually slightly lighter than Regular, but sometimes | |
138 | (mainly in fonts from DTL and FontFont/FSI) slightly *heavier*. | |
138 | - Book is usually slightly lighter than Regular (and so could be mapped to "sl"), | |
139 | but sometimes (mainly in fonts from DTL and FontFont/FSI) slightly *heavier*. | |
139 | 140 | - Likewise, Medium can really be two different things: |
140 | 141 | - a synonym for Semibold |
141 | 142 | - (especially in newer fonts) an extra step between Regular and Semibold |
142 | 143 | I treat it as if it's always the first. |
143 | 144 | - Heavy can mean very different things; it's often heavier than Black, |
144 | but sometimes it's a synonym for Extrabold, and in Futura it's even | |
145 | lighter than Bold. I treat it here as "very black". | |
145 | but sometimes it's a synonym for Extrabold, and in some families (Futura) | |
146 | it's even lighter than Bold. I treat it here as "very black". | |
146 | 147 | - Font families that have both Condensed and Compressed widths |
147 | 148 | seem to define Compressed as narrower than Condensed. |
148 | - In Basic Sans and Input (which are the only families I know with both | |
149 | Narrow and Condensed), Narrow is a bit wider than Condensed. | |
150 | So I mapped Narrow to "sc". | |
149 | - In Basic Sans (which is the only family I know with both Narrow and Condensed | |
150 | fonts) Narrow is a bit wider than Condensed. So I mapped Narrow to "sc". | |
151 | 151 | - Extended and Expanded seem to be used interchangeably. |
152 | - I have never seen any (Extra-,Ultra)(Extended,Expanded,Wide) fonts, | |
153 | so the ex and ux entries are currently empty. | |
152 | - I have never seen any (Extra-,Ultra)(Extended,Expanded,Wide) fonts in the wild, | |
153 | so the ex and ux entries are currently empty | |
154 | 154 | |
155 | 155 | =end Comment |
156 | 156 | |
157 | 157 | =cut |
158 | 158 | |
159 | my @NFSS_WEIGHT = ( | |
160 | ul => [ qw( ultralight thin hair hairline eight four two ) ], | |
161 | el => [ qw( extralight ) ], | |
159 | my %NFSS_WEIGHT = ( | |
160 | ul => [ qw( ultralight hair hairline eight four two ) ], | |
161 | el => [ qw( extralight thin ) ], | |
162 | 162 | l => [ qw( light ) ], |
163 | 163 | sl => [ qw( semilight blond ) ], |
164 | 164 | '' => [ qw( regular text book ) ], |
168 | 168 | ub => [ qw( ultrabold black heavy extrablack ultra ultrablack ultraheavy |
169 | 169 | poster super ) ], |
170 | 170 | ); |
171 | my %NFSS_WEIGHT = @NFSS_WEIGHT; | |
172 | @NFSS_WEIGHT = grep { !ref } @NFSS_WEIGHT; | |
173 | my @WEIGHTS = map { @{$_} } values %NFSS_WEIGHT; | |
174 | ||
175 | my @NFSS_WIDTH = ( | |
171 | ||
172 | my %NFSS_WIDTH = ( | |
176 | 173 | uc => [ qw( ultracondensed extracompressed ultracompressed ) ], |
177 | 174 | ec => [ qw( extracondensed cmp comp compressed compact ) ], |
178 | 175 | c => [ qw( cond condensed ) ], |
183 | 180 | ex => [ ], |
184 | 181 | ux => [ ], |
185 | 182 | ); |
186 | my %NFSS_WIDTH = @NFSS_WIDTH; | |
187 | @NFSS_WIDTH = grep { !ref } @NFSS_WIDTH; | |
188 | my @WIDTHS = map { @{$_} } values %NFSS_WIDTH; | |
189 | 183 | |
190 | 184 | =begin Comment |
191 | 185 | |
192 | The NFSS_SHAPE table maps various shape names to NFSS codes. | |
186 | The %NFSS_SHAPE table maps various shape names to NFSS codes. | |
193 | 187 | |
194 | 188 | Note that this table works the other way around compared to |
195 | 189 | the two previous tables; it directly maps shape names to NFSS codes. |
200 | 194 | For shapes, that's not the case; font families don't have both Slanted and |
201 | 195 | Oblique shapes, since these are just different names for the same thing. |
202 | 196 | |
203 | Like in the other NFSS_* tables, entries may be added to teach autoinst | |
197 | Like in the other %NFSS_* tables, entries may be added to teach autoinst | |
204 | 198 | about new shapes. |
205 | 199 | |
206 | 200 | =end Comment |
207 | 201 | |
208 | 202 | =cut |
209 | 203 | |
210 | my @NFSS_SHAPE = ( | |
204 | my %NFSS_SHAPE = ( | |
211 | 205 | roman => 'n', |
212 | 206 | upright => 'n', |
213 | 207 | italic => 'it', |
220 | 214 | oblique => 'sl', |
221 | 215 | slanted => 'sl', |
222 | 216 | slant => 'sl', |
223 | romani => 'n', # Silentium Pro has two roman shapes, but no italic; | |
217 | romani => 'n', # Adobe Silentium Pro has two roman shapes, but no italic; | |
224 | 218 | romanii => 'it', # so we cheat by mapping the second roman shape to 'it' |
225 | 219 | ); |
226 | my %NFSS_SHAPE = @NFSS_SHAPE; | |
227 | 220 | |
228 | 221 | =begin Comment |
229 | 222 | |
230 | 223 | The %SHAPE table is used in deciding which font shapes |
231 | (normal, small caps, swash or textcomp) to generate. | |
224 | (normal, small caps, swash, titling or textcomp) to generate. | |
232 | 225 | |
233 | 226 | Each key in this table names a shape; the corresponding value |
234 | 227 | is an anonymous hash with several key/value pairs: |
277 | 270 | # comes last in the command line; else 'aalt' might be overridden |
278 | 271 | swash => { |
279 | 272 | code => { n => 'nw', it => 'sw' }, |
280 | reqd => [ 'swsh' ], | |
281 | nice => [ 'kern', 'liga', 'dlig' ], | |
273 | reqd => [ 'swsh', 'dlig' ], | |
274 | nice => [ 'kern', 'liga' ], | |
282 | 275 | extra => '--include-alternates="*.swash" --feature=aalt', |
283 | 276 | name => 'swash', |
277 | }, | |
278 | titling => { | |
279 | code => { n => 'tl', it => 'tlit', sl => 'tlsl' }, | |
280 | reqd => [ 'titl', 'case', 'cpsp' ], | |
281 | nice => [ 'kern', 'liga' ], | |
282 | extra => '', | |
283 | name => 'titling', | |
284 | 284 | }, |
285 | 285 | textcomp => { |
286 | 286 | code => { n => 'n', it => 'it', sl => 'sl' }, |
303 | 303 | my %SSUB_SHAPE = ( |
304 | 304 | sl => 'it', |
305 | 305 | scsl => 'scit', |
306 | tlsl => 'tlit', | |
306 | 307 | it => 'sl', |
307 | 308 | scit => 'scsl', |
309 | tlit => 'tlsl', | |
308 | 310 | ); |
309 | 311 | |
310 | 312 | =begin Comment |
341 | 343 | reqd => [ ], |
342 | 344 | nice => [ ], |
343 | 345 | extra => '', |
344 | shapes => [ 'normal', 'smallcaps', 'swash', 'textcomp' ], | |
346 | shapes => [ 'normal', 'smallcaps', 'swash', 'titling', 'textcomp' ], | |
345 | 347 | }, |
346 | 348 | LF => { |
347 | 349 | reqd => [ ], |
348 | 350 | nice => [ ], |
349 | 351 | extra => '', |
350 | shapes => [ 'normal', 'smallcaps', 'swash', 'textcomp' ], | |
352 | shapes => [ 'normal', 'smallcaps', 'swash', 'titling', 'textcomp' ], | |
351 | 353 | }, |
352 | 354 | TOsF => { |
353 | 355 | reqd => [ ], |
385 | 387 | extra => '--ligkern="* {KL} *"', |
386 | 388 | shapes => [ 'normal' ], |
387 | 389 | }, |
388 | Titl => { | |
389 | reqd => [ 'titl' ], | |
390 | nice => [ 'kern', 'liga' ], | |
391 | extra => '', | |
392 | shapes => [ 'normal' ], | |
393 | }, | |
394 | 390 | Orn => { |
395 | 391 | reqd => [ 'ornm' ], |
396 | 392 | nice => [ ], |
461 | 457 | # since this requires knowing which inferior figures this font supports; |
462 | 458 | # so we have to do the font info parsing first. |
463 | 459 | if ($ARGV{inferiors} eq 'auto') { |
464 | Fontinfo::handle_auto_inferiors(@fonts); | |
465 | } | |
460 | FONT: | |
461 | for my $font (@fonts) { | |
462 | for my $inf (qw(subs sinf dnom)) { | |
463 | if (exists $font->{feature}{$inf}) { | |
464 | $ARGV{inferiors} = $inf; | |
465 | $STYLE{Inf}{reqd} = [$inf]; | |
466 | last FONT; | |
467 | } | |
468 | } | |
469 | } | |
470 | } | |
471 | # If we didn't find any inferior figures, delete the 'Inf' entry | |
472 | # frin the %STYLE table to indicate we don't want to generate this style. | |
473 | delete $STYLE{Inf} if $ARGV{inferiors} eq 'auto'; | |
466 | 474 | |
467 | 475 | # For each font, figure out the styles, shapes and encodings to generate |
468 | 476 | my @worklist |
482 | 490 | push @{$fddata{$family}{$encoding}{$style}{$series}{$shape}}, |
483 | 491 | [ $minsize, $maxsize, $item->{fontname} ]; |
484 | 492 | } |
485 | ||
486 | # Decide to which weights and widths we'll map the standard NFSS codes | |
487 | decide_nfss_mappings(@fonts); | |
488 | 493 | |
489 | 494 | create_logfile(@worklist); |
490 | 495 | |
598 | 603 | my ($font, $style, $shape, $encoding) |
599 | 604 | = @{$item}{qw(font style shape encoding)}; |
600 | 605 | |
601 | # make unique copy of fontdata, since we're modifying it; | |
602 | # otherwise, the mergesmallcaps only works for | |
603 | # the first encoding in the list | |
604 | my %font = %$font; | |
605 | $font = $item->{font} = \%font; | |
606 | ||
607 | # handle fonts that put small caps fonts into separate family | |
608 | if ($ARGV{mergesmallcaps}) { | |
609 | if ($font->{family} =~ s/smallcaps$//xmsi) { | |
610 | $shape = $item->{shape} = 'smallcaps'; | |
611 | } | |
612 | } | |
613 | ||
614 | 606 | # generate unique name for this font |
615 | 607 | $item->{fontname} = join '-', grep { $_ } $font->{name}, |
616 | 608 | lc $style, |
644 | 636 | } |
645 | 637 | |
646 | 638 | #----------------------------------------------------------------------- |
647 | # Modify NFSS_WEIGHT and _WIDTH tables: pick one choice for each NFSS code | |
648 | #----------------------------------------------------------------------- | |
649 | sub decide_nfss_mappings { | |
650 | my ( %weight, %width ); | |
651 | for my $font (@_) { | |
652 | $weight{ $font->{weight} } = 1; | |
653 | $width{ $font->{width} } = 1; | |
654 | } | |
655 | ||
656 | NFSSWEIGHT: | |
657 | for my $nfssweight (@NFSS_WEIGHT) { | |
658 | for my $weight ( @{$NFSS_WEIGHT{$nfssweight}} ) { | |
659 | if ( $weight{$weight} ) { | |
660 | $NFSS_WEIGHT{$nfssweight} = [ $weight ]; | |
661 | next NFSSWEIGHT; | |
662 | } | |
663 | } | |
664 | $NFSS_WEIGHT{$nfssweight} = []; | |
665 | } | |
666 | if ( !$ARGV{el} and !$ARGV{ul} ) { | |
667 | if ( @{$NFSS_WEIGHT{ul}} | |
668 | and $NFSS_WEIGHT{ul}[0] ne 'ultralight' | |
669 | and !@{$NFSS_WEIGHT{el}} ) { | |
670 | $NFSS_WEIGHT{el} = $NFSS_WEIGHT{ul}; | |
671 | $NFSS_WEIGHT{ul} = []; | |
672 | } | |
673 | } | |
674 | if ( !$ARGV{eb} and !$ARGV{ub} ) { | |
675 | if ( @{$NFSS_WEIGHT{ub}} | |
676 | and $NFSS_WEIGHT{ub}[0] ne 'ultrabold' | |
677 | and !@{$NFSS_WEIGHT{eb}} ) { | |
678 | $NFSS_WEIGHT{eb} = $NFSS_WEIGHT{ub}; | |
679 | $NFSS_WEIGHT{ub} = []; | |
680 | } | |
681 | } | |
682 | ||
683 | NFSSWIDTH: | |
684 | for my $nfsswidth (@NFSS_WIDTH) { | |
685 | for my $width ( @{$NFSS_WIDTH{$nfsswidth}} ) { | |
686 | if ( $width{$width} ) { | |
687 | $NFSS_WIDTH{$nfsswidth} = [ $width ]; | |
688 | next NFSSWIDTH; | |
689 | } | |
690 | } | |
691 | $NFSS_WIDTH{$nfsswidth} = []; | |
692 | } | |
693 | } | |
694 | ||
695 | #----------------------------------------------------------------------- | |
696 | 639 | # Dump all relevant info to the logfile |
697 | 640 | #----------------------------------------------------------------------- |
698 | 641 | sub create_logfile { |
702 | 645 | || $a->{style} cmp $b->{style} |
703 | 646 | } @_; |
704 | 647 | |
705 | if (-e $ARGV{logfile}) { | |
706 | print "[INFO]: file '$ARGV{logfile}' already exists;\n" . | |
707 | " appending new log data to end\n\n"; | |
708 | } | |
709 | open my $LOG, '>>', $ARGV{logfile} | |
648 | open my $LOG, '>', $ARGV{logfile} | |
710 | 649 | or die "$0: cannot create $ARGV{logfile}: $!"; |
711 | 650 | |
712 | 651 | print {$LOG} <<"END_ARGUMENTS"; |
713 | 652 | |
714 | ||
715 | ############################################################################ | |
716 | ||
717 | ||
718 | @{[ POSIX::strftime("[%F %T]", localtime time) ]} $0 | |
719 | ||
720 | ||
721 | "$ARGV{cmdline}" | |
722 | ||
723 | ||
724 | ---------------------------------------------------------------------------- | |
653 | $ARGV{cmdline} | |
654 | ||
655 | ||
656 | **************************************************************************** | |
725 | 657 | |
726 | 658 | |
727 | 659 | I'm using the following options: |
745 | 677 | inferiors: $ARGV{inferiors} |
746 | 678 | ornaments: @{[ $ARGV{ornaments} ? 'yes' : 'no' ]} |
747 | 679 | fractions: @{[ $ARGV{fractions} ? 'yes' : 'no' ]} |
748 | ligatures: @{[ $ARGV{ligatures} ? 'yes' : 'no' ]} | |
749 | 680 | |
750 | 681 | dry run/real: @{[ $ARGV{dryrun} ? 'dry run' : 'real' ]} |
751 | 682 | auto/manual: @{[ $ARGV{manual} ? 'manual' : 'auto' ]} |
752 | 683 | target: $ARGV{target} |
753 | 684 | extra: @{[ $ARGV{extra} || '<empty>' ]} |
754 | 685 | |
755 | figurekern: @{[ $ARGV{figurekern} ? 'no action' : 'remove' ]} | |
756 | mergewidths: @{[ $ARGV{mergewidths} ? 'yes' : 'no' ]} | |
757 | mergesmallcaps: @{[ $ARGV{mergesmallcaps} ? 'yes' : 'no' ]} | |
686 | figurekern: @{[ $ARGV{figurekern} ? 'no action' : 'remove' ]} | |
687 | mergewidths: @{[ $ARGV{mergewidths} ? 'yes' : 'no' ]} | |
758 | 688 | |
759 | 689 | |
760 | 690 | font files: |
761 | 691 | @{[ join "\n ", @ARGV ]} |
762 | 692 | |
763 | 693 | END_ARGUMENTS |
764 | ||
765 | printf {$LOG} "\n" . '-' x 76 . "\n\n\nNFSS mappings:\n\n"; | |
766 | for my $weight (@NFSS_WEIGHT) { | |
767 | printf {$LOG} " %-3s => %s\n", | |
768 | $weight || 'm', $NFSS_WEIGHT{$weight}[0] || ''; | |
769 | } | |
770 | printf {$LOG} "\n"; | |
771 | for my $width (@NFSS_WIDTH) { | |
772 | printf {$LOG} " %-3s => %s\n", | |
773 | $width || 'm', $NFSS_WIDTH{$width}[0] || ''; | |
774 | } | |
775 | printf {$LOG} "\n"; | |
776 | ||
777 | return if $ARGV{verbose} < 1; | |
778 | 694 | |
779 | 695 | my ($prevfn, $prevsty, $prevenc) = ('') x 3; |
780 | 696 | my @cmds; |
781 | 697 | for my $item (@worklist) { |
782 | 698 | if ($prevfn ne $item->{font}{filename}) { |
699 | push @cmds, "\n" . '*' x 76; | |
783 | 700 | print {$LOG} <<"END_FONTINFO"; |
784 | 701 | |
785 | ------------------------------------------------------------------------ | |
786 | ||
787 | $item->{font}{filename} | |
702 | ||
703 | **************************************************************************** | |
704 | ||
705 | ||
706 | $item->{font}{filename} | |
788 | 707 | Name: $item->{font}{name} |
789 | 708 | Family: $item->{font}{family} |
790 | 709 | Subfamily: $item->{font}{subfamily} |
795 | 714 | Features: @{[ join ', ', sort keys %{$item->{font}{feature}} ]} |
796 | 715 | |
797 | 716 | |
798 | Generating these encodings, figure styles and shapes: | |
799 | ||
800 | ENC STYLE SHAPE FEATURES USED | |
717 | Generating these encodings, figure styles and shapes: | |
718 | ||
719 | ENC STYLE SHAPE FEATURES USED | |
720 | -------------------------------------------------------------------- | |
801 | 721 | END_FONTINFO |
802 | 722 | } |
803 | 723 | if ($prevenc ne $item->{encoding}[1] |
804 | 724 | || $prevsty ne $item->{style}) { |
805 | 725 | print {$LOG} "\n"; |
806 | 726 | } |
807 | printf {$LOG} " %-3s %-4s %-4s %s\n", | |
727 | printf {$LOG} " %-3s %-4s %-4s %s\n", | |
808 | 728 | $item->{encoding}[1], |
809 | 729 | $item->{style}, |
810 | 730 | $item->{fdshape}, |
817 | 737 | push @cmds, $item->{cmdline}; |
818 | 738 | } |
819 | 739 | |
820 | return if $ARGV{verbose} < 2; | |
821 | 740 | print {$LOG} join "\n\n", @cmds; |
822 | 741 | print {$LOG} "\n"; |
823 | 742 | close $LOG; |
879 | 798 | ? qq(--coding-scheme="$SCHEME{$item->{encoding}[0]}") |
880 | 799 | : ''), |
881 | 800 | (map { "--feature=$_" } @{$item->{features}}), |
882 | ($ARGV{ligatures} | |
883 | ? ( '--ligkern="f i =: fi"', | |
801 | ((grep { $_ eq 'liga' } @{$item->{features}}) | |
802 | ? '' | |
803 | : ( '--ligkern="f i =: fi"', | |
884 | 804 | '--ligkern="f l =: fl"', |
885 | 805 | '--ligkern="f f =: ff"', |
886 | 806 | '--ligkern="ff i =: ffi"', |
887 | '--ligkern="ff l =: ffl"' ) | |
888 | : ''), | |
807 | '--ligkern="ff l =: ffl"' )), | |
889 | 808 | $STYLE{$item->{style}}{extra}, |
890 | 809 | $SHAPE{$item->{shape}}{extra}, |
891 | 810 | $ARGV{extra}, |
953 | 872 | Use this style for subscripts (see docs) |
954 | 873 | -(no)ornaments Toggle creation of ornament fonts |
955 | 874 | -(no)fractions Toggle creation of fonts with digits for fractions |
956 | -(no)ligatures Toggle manual addition of f-ligatures to font | |
957 | ||
958 | -serif Install font as serif font | |
875 | ||
959 | 876 | -sanserif Install font as sanserif font |
960 | 877 | -typewriter Install font as typewriter font |
961 | 878 | |
973 | 890 | |
974 | 891 | -(no)figurekern Keep or remove kerns between tabular figures |
975 | 892 | -(no)mergewidths Merge Condended/Extended subfamilies with main family |
976 | -(no)mergesmallcaps Merge small caps subfamilies with main family | |
977 | ||
978 | -nfssweight=xx=yyyy Map the "xx" NFSS code to the "yyyy" weight | |
979 | -nfsswidth=xx=yyyy Map the "xx" NFSS code to the "yyyy" width | |
980 | 893 | |
981 | 894 | -help Print this text and exit |
982 | 895 | -doc Print the complete documentation and exit |
983 | 896 | -dryrun Don't generate fonts, only log what would be done |
984 | -logfile="FILE" Write log data to "FILE" (default: <fontfamily>.log) | |
985 | -verbose Print more data to log file | |
986 | (repeat for even higher verbosity) | |
897 | ||
987 | 898 | font[s] The fonts (.otf or .ttf format) to install. |
988 | 899 | |
989 | 900 | Please report any bugs or suggestions to <marcpenninga@gmail.com>. |
991 | 902 | |
992 | 903 | # Default values for the command-line arguments |
993 | 904 | %ARGV = ( |
994 | encoding => 'OT1,T1,LY1', | |
995 | textcomp => '2', # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no) | |
996 | lining => '1', # 0 = no, 1 = yes | |
997 | oldstyle => '1', # 0 = no, 1 = yes | |
998 | proportional => '1', # 0 = no, 1 = yes | |
999 | tabular => '1', # 0 = no, 1 = yes | |
1000 | smallcaps => '1', # 0 = no, 1 = yes | |
1001 | swash => '1', # 0 = no, 1 = yes | |
1002 | titling => '1', # 0 = no, 1 = yes | |
1003 | superiors => '1', # 0 = no, 1 = yes | |
1004 | inferiors => 'none', # possible values: none, auto, subs, sinf, dnom | |
1005 | ornaments => '1', # 0 = no, 1 = yes | |
1006 | fractions => '0', # 0 = no, 1 = yes | |
1007 | ligatures => '0', # 0 = no, 1 = yes | |
1008 | nfss => 'rm', | |
1009 | fig_height => 'lnum', | |
1010 | fig_width => 'tnum', | |
1011 | extra => '', | |
1012 | target => '', | |
1013 | vendor => 'lcdftools', | |
1014 | typeface => '', | |
1015 | updmap => '1', # 0 = no, 1 = yes | |
1016 | manual => '0', # 0 = no, 1 = yes | |
1017 | dryrun => '0', # 0 = no, 1 = yes | |
1018 | logfile => '', | |
1019 | figurekern => '1', # 0 = no, 1 = yes | |
1020 | mergewidths => '1', # 0 = no, 1 = yes | |
1021 | mergesmallcaps => '1', # 0 = no, 1 = yes | |
1022 | verbose => 0, | |
905 | encoding => 'OT1,T1,LY1', | |
906 | textcomp => '2', # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no) | |
907 | lining => '1', # 0 = no, 1 = yes | |
908 | oldstyle => '1', # 0 = no, 1 = yes | |
909 | proportional => '1', # 0 = no, 1 = yes | |
910 | tabular => '1', # 0 = no, 1 = yes | |
911 | smallcaps => '1', # 0 = no, 1 = yes | |
912 | swash => '1', # 0 = no, 1 = yes | |
913 | titling => '1', # 0 = no, 1 = yes | |
914 | superiors => '1', # 0 = no, 1 = yes | |
915 | inferiors => 'none', # possible values: none, auto, subs, sinf, dnom | |
916 | ornaments => '1', # 0 = no, 1 = yes | |
917 | fractions => '0', # 0 = no, 1 = yes | |
918 | nfss => 'rm', | |
919 | fig_height => 'lnum', | |
920 | fig_width => 'tnum', | |
921 | extra => '', | |
922 | target => '', | |
923 | vendor => 'lcdftools', | |
924 | typeface => '', | |
925 | updmap => '1', # 0 = no, 1 = yes | |
926 | manual => '0', # 0 = no, 1 = yes | |
927 | dryrun => '0', # 0 = no, 1 = yes | |
928 | logfile => 'autoinst.log', | |
929 | figurekern => '1', # 0 = no, 1 = yes | |
930 | mergewidths => '0', # 0 = no, 1 = yes | |
1023 | 931 | ); |
1024 | 932 | |
1025 | 933 | #----------------------------------------------------------------------- |
1044 | 952 | 'inferiors=s' => \$ARGV{inferiors}, |
1045 | 953 | 'ornaments!' => \$ARGV{ornaments}, |
1046 | 954 | 'fractions!' => \$ARGV{fractions}, |
1047 | 'ligatures!' => \$ARGV{ligatures}, | |
1048 | 'serif' => sub { $ARGV{nfss} = 'rm' }, | |
1049 | 955 | 'sanserif' => sub { $ARGV{nfss} = 'sf' }, |
1050 | 956 | 'typewriter' => sub { $ARGV{nfss} = 'tt' }, |
1051 | 957 | 'defaultlining' => sub { $ARGV{fig_height} = 'lnum' }, |
1061 | 967 | 'manual' => \$ARGV{manual}, |
1062 | 968 | 'figurekern!' => \$ARGV{figurekern}, |
1063 | 969 | 'mergewidths!' => \$ARGV{mergewidths}, |
1064 | 'mergesmallcaps!' => \$ARGV{mergesmallcaps}, | |
1065 | 'logfile=s' => \$ARGV{logfile}, | |
1066 | 'verbose+' => \$ARGV{verbose}, | |
1067 | 'nfssweight=s%' => sub { | |
1068 | my ( $ignored, $key, $values ) = @_; | |
1069 | my @values = split m/,/, lc $values; | |
1070 | $NFSS_WEIGHT{$key} = \@values; | |
1071 | $ARGV{$key} = 'user-defined'; | |
1072 | }, | |
1073 | 'nfsswidth=s%' => sub { | |
1074 | my ( $ignored, $key, $values ) = @_; | |
1075 | my @values = split m/,/, lc $values; | |
1076 | $NFSS_WIDTH{$key} = \@values; | |
1077 | $ARGV{$key} = 'user-defined'; | |
1078 | }, | |
970 | 'verbose+' => sub {}, | |
1079 | 971 | ) |
1080 | 972 | or die "$USAGE"; |
1081 | 973 | |
1083 | 975 | |
1084 | 976 | delete $SHAPE{smallcaps} unless $ARGV{smallcaps}; |
1085 | 977 | delete $SHAPE{swash} unless $ARGV{swash}; |
1086 | ||
1087 | delete $STYLE{Titl} unless $ARGV{titling}; | |
978 | delete $SHAPE{titling} unless $ARGV{titling}; | |
979 | ||
1088 | 980 | delete $STYLE{Sup} unless $ARGV{superiors}; |
1089 | 981 | delete $STYLE{Orn} unless $ARGV{ornaments}; |
1090 | 982 | delete @STYLE{qw(Numr Dnom)} unless $ARGV{fractions}; |
1245 | 1137 | # 1. Search for matching widths before matching weights |
1246 | 1138 | # (as none of the widths is a proper substring of some weight) |
1247 | 1139 | # 2. Remove any recognised search string from the 'fullinfo' |
1248 | for my $width ( mqrs(@WIDTHS) ) { | |
1140 | for my $width ( mqrs( map { @{$_} } values %NFSS_WIDTH ) ) { | |
1249 | 1141 | if ($fullinfo =~ s/${width}//gxmsi) { |
1250 | 1142 | $info->{width} = $width; |
1251 | 1143 | last; |
1252 | 1144 | } |
1253 | 1145 | } |
1254 | for my $weight ( mqrs(@WEIGHTS) ) { | |
1146 | for my $weight ( mqrs( map { @{$_} } values %NFSS_WEIGHT ) ) { | |
1255 | 1147 | if ($fullinfo =~ s/${weight}//gxmsi) { |
1256 | 1148 | $info->{weight} = $weight; |
1257 | 1149 | last; |
1276 | 1168 | $info->{family} = $data{family}; |
1277 | 1169 | $info->{subfamily} = $data{subfamily}; |
1278 | 1170 | |
1279 | if ( !$ARGV{logfile} ) { | |
1280 | $ARGV{logfile} = sprintf "%s.log", lc $info->{family} | |
1281 | } | |
1282 | 1171 | # Some font families put condensed or extended widths into separate families; |
1283 | 1172 | # we provide an option to merge these with the 'main' font family. |
1284 | 1173 | if ($ARGV{mergewidths}) { |
1285 | my $widths = join '|', mqrs(@WIDTHS); | |
1174 | my $widths = join '|', mqrs( map { @{$_} } values %NFSS_WIDTH ); | |
1286 | 1175 | if ($info->{width} eq 'regular' |
1287 | 1176 | && $info->{family} =~ m/(.+?) [ ]* (${widths})$/xmsi) |
1288 | 1177 | { |
1307 | 1196 | |
1308 | 1197 | # We define 'series' as 'weight + width'. This matches NFSS, but contradicts |
1309 | 1198 | # how most fonts are named (which is 'width + weight'). |
1310 | $info->{series} | |
1199 | $info->{series} | |
1311 | 1200 | = ($info->{width} eq 'regular') ? $info->{weight} |
1312 | 1201 | : ($info->{weight} eq 'regular') ? $info->{width} |
1313 | 1202 | : $info->{weight} . $info->{width} |
1314 | 1203 | ; |
1315 | 1204 | |
1316 | return; | |
1205 | return $info; | |
1317 | 1206 | } |
1318 | 1207 | |
1319 | 1208 | #----------------------------------------------------------------------- |
1344 | 1233 | $info->{feature}{kern} = 1 if grep { m/\d+ \s+ kern/xms } <$otfinfo>; |
1345 | 1234 | close $otfinfo; |
1346 | 1235 | |
1347 | return; | |
1236 | return $info; | |
1348 | 1237 | } |
1349 | 1238 | |
1350 | 1239 | #----------------------------------------------------------------------- |
1389 | 1278 | } |
1390 | 1279 | close $otfinfo; |
1391 | 1280 | |
1392 | return; | |
1281 | return $info; | |
1393 | 1282 | } |
1394 | 1283 | |
1395 | 1284 | |
1414 | 1303 | - Run 'autoinst' on a smaller set of fonts, |
1415 | 1304 | omitting the ones that weren't parsed correctly; |
1416 | 1305 | - Add the missing widths, weights or shapes to the tables |
1417 | 'NFSS_WIDTH', 'NFSS_WEIGHT' or 'NFSS_SHAPE' near the top | |
1306 | '%NFSS_WIDTH', '%NFSS_WEIGHT' or '%NFSS_SHAPE' near the top | |
1418 | 1307 | of the source code; |
1419 | 1308 | |
1420 | 1309 | Please also send a bug report to the author. |
1492 | 1381 | return $enc_name; |
1493 | 1382 | } |
1494 | 1383 | |
1495 | #----------------------------------------------------------------------- | |
1496 | # Handle the -inferiors=auto option | |
1497 | #----------------------------------------------------------------------- | |
1498 | sub handle_auto_inferiors { | |
1499 | FONT: | |
1500 | for my $font (@_) { | |
1501 | for my $inf (qw(subs sinf dnom)) { | |
1502 | if (exists $font->{feature}{$inf}) { | |
1503 | $ARGV{inferiors} = $inf; | |
1504 | $STYLE{Inf}{reqd} = [$inf]; | |
1505 | last FONT; | |
1506 | } | |
1507 | } | |
1508 | } | |
1509 | ||
1510 | # If we didn't find any inferior figures, delete the 'Inf' entry | |
1511 | # from the %STYLE table to indicate we don't want to generate this style. | |
1512 | delete $STYLE{Inf} if $ARGV{inferiors} eq 'auto'; | |
1513 | } | |
1514 | ||
1515 | 1384 | |
1516 | 1385 | ############################################################################ |
1517 | 1386 | |
1519 | 1388 | package LaTeX; |
1520 | 1389 | |
1521 | 1390 | #----------------------------------------------------------------------- |
1522 | # Create a LaTeX style file | |
1391 | # Create a Latex style file | |
1523 | 1392 | #----------------------------------------------------------------------- |
1524 | 1393 | sub write_stylefile { |
1525 | 1394 | my ($fam, $data) = @_; |
1553 | 1422 | \RequirePackage{fontaxes} |
1554 | 1423 | END_STY_FONTAXES_START |
1555 | 1424 | |
1425 | if ($seen{tl} or $seen{tlit}) { | |
1426 | print {$STY} <<'END_STY_FONTAXES_TL'; | |
1427 | \providecommand{\tldefault}{tl} | |
1428 | \DeclareRobustCommand\tlshape{\not@math@alphabet\tlshape\relax | |
1429 | \fontsecondaryshape\tldefault\selectfont} | |
1430 | \DeclareTextFontCommand{\texttl}{\tlshape} | |
1431 | \let\texttitling\texttl | |
1432 | \fa@naming@exception{shape}{{n}{tl}}{tl} | |
1433 | \fa@naming@exception{shape}{{it}{tl}}{tlit} | |
1434 | \fa@naming@exception{shape}{{sl}{tl}}{tlsl} | |
1435 | ||
1436 | END_STY_FONTAXES_TL | |
1437 | } | |
1556 | 1438 | |
1557 | 1439 | if ($seen{nw} or $seen{sw}) { |
1558 | 1440 | print {$STY} <<'END_STY_FONTAXES_SW'; |
1586 | 1468 | \let\textinferior\textin |
1587 | 1469 | |
1588 | 1470 | END_STY_FONTAXES_INF |
1589 | } | |
1590 | ||
1591 | if ($seen{Titl}) { | |
1592 | print {$STY} <<'END_STY_FONTAXES_TITL'; | |
1593 | \fa@naming@exception{figures}{{titlingshape}{proportional}}{Titl} | |
1594 | \fa@naming@exception{figures}{{titlingshape}{tabular}}{Titl} | |
1595 | \def\tlshape{\@nomath\tlshape | |
1596 | \fontfigurestyle{titlingshape}\selectfont} | |
1597 | \DeclareTextFontCommand{\texttl}{\tlshape} | |
1598 | \let\texttitling\texttl | |
1599 | ||
1600 | END_STY_FONTAXES_TITL | |
1601 | 1471 | } |
1602 | 1472 | |
1603 | 1473 | if ($seen{Orn}) { |
1669 | 1539 | : die "[ERROR] Internal bug, please report!"; |
1670 | 1540 | |
1671 | 1541 | my $default_bold; |
1672 | for my $series (qw(heavy black extrabold demibold semibold bold)) { | |
1542 | for my $series (qw(heavy black extrabold demibold semibold bold)) | |
1543 | { | |
1673 | 1544 | if ( $seen{$series} ) { |
1674 | 1545 | print {$STY} |
1675 | 1546 | "\\DeclareOptionX{$series}{\\edef\\bfseries\@$ARGV{nfss}", |
1783 | 1654 | |
1784 | 1655 | print {$FD} <<"END_COMMENT"; |
1785 | 1656 | % |
1786 | % Extra 'ssub' rules to map the standard NFSS codes to our fancy names | |
1657 | % ==== Extra 'ssub' rules to map the standard NFSS codes to our fancy names ==== | |
1787 | 1658 | % |
1788 | 1659 | END_COMMENT |
1789 | 1660 | my %seen; |
1790 | 1661 | NFSSWEIGHT: |
1791 | for my $nfssweight (@NFSS_WEIGHT) { | |
1662 | for my $nfssweight (keys %NFSS_WEIGHT) { | |
1792 | 1663 | NFSSWIDTH: |
1793 | for my $nfsswidth (@NFSS_WIDTH) { | |
1664 | for my $nfsswidth (keys %NFSS_WIDTH) { | |
1794 | 1665 | my $nfssseries = ( $nfssweight . $nfsswidth) || 'm'; |
1795 | 1666 | |
1796 | 1667 | for my $weight ( @{$NFSS_WEIGHT{$nfssweight}} ) { |
1860 | 1731 | =head1 NAME |
1861 | 1732 | |
1862 | 1733 | autoinst - wrapper around the F<LCDF TypeTools>, |
1863 | for installing and using OpenType fonts in LaTeX. | |
1734 | for installing and using OpenType fonts in (La)TeX. | |
1864 | 1735 | |
1865 | 1736 | |
1866 | 1737 | =head1 SYNOPSIS |
1906 | 1777 | |
1907 | 1778 | Small caps |
1908 | 1779 | |
1780 | =item I<sw> | |
1781 | ||
1782 | Swash | |
1783 | ||
1784 | =item I<tl> | |
1785 | ||
1786 | Titling shape. Meant for all-caps text; letterspacing and the positioning of | |
1787 | punctuation characters have been adjusted to suit all-caps text. | |
1788 | (This shape is only generated for the families with lining digits, | |
1789 | since old-style digits make no sense with all-caps text.) | |
1790 | ||
1909 | 1791 | =item I<scit>, I<scsl> |
1910 | 1792 | |
1911 | 1793 | Italic and slanted small caps |
1912 | 1794 | |
1913 | =item I<sw> | |
1914 | ||
1915 | Swash | |
1916 | ||
1917 | 1795 | =item I<nw> |
1918 | 1796 | |
1919 | "Upright swash" | |
1797 | "Upright swash"; usually roman text with a few "oldstyle" ligatures | |
1798 | like ct, sp and st. | |
1799 | ||
1800 | =item I<tlit>, I<tlsl> | |
1801 | ||
1802 | Italic and slanted titling text | |
1920 | 1803 | |
1921 | 1804 | =back |
1922 | 1805 | |
1931 | 1814 | |
1932 | 1815 | Families with superiors, inferiors, numerators and denominators, |
1933 | 1816 | in roman, italic and slanted shapes. |
1934 | ||
1935 | =item - | |
1936 | ||
1937 | Families with "Titling" characters; these "... replace the default glyphs | |
1938 | with corresponding forms designed specifically for titling. | |
1939 | These may be all-capital and/or larger on the body, | |
1940 | and adjusted for viewing at larger sizes" | |
1941 | (according to the OpenType Specification). | |
1942 | 1817 | |
1943 | 1818 | =item - |
1944 | 1819 | |
1985 | 1860 | inferior characters; usually only digits and some punctuation, |
1986 | 1861 | normal forms for other characters |
1987 | 1862 | |
1988 | =item I<Titl> | |
1989 | ||
1990 | Titling characters; see above. | |
1991 | ||
1992 | 1863 | =item I<Orn> |
1993 | 1864 | |
1994 | 1865 | ornaments |
2005 | 1876 | |
2006 | 1877 | The individual fonts are named I<< <FontName>-<suffix>-<shape>-<enc> >>, |
2007 | 1878 | where I<< <suffix> >> is the same as above (but in lowercase), |
2008 | I<< <shape> >> is either empty, "sc" or "swash", | |
1879 | I<< <shape> >> is either empty, "sc", "swash" or "titling", | |
2009 | 1880 | and I<< <enc> >> is the encoding (also in lowercase). |
2010 | 1881 | A typical name in this scheme would be "FiraSans-Light-osf-sc-ly1". |
2011 | ||
2012 | ||
2013 | =head2 About the log file | |
2014 | ||
2015 | B<autoinst> writes some info about what it thinks it's doing to a log file. | |
2016 | By default this is called F<< <fontfamily>.log >>, | |
2017 | but this choice can be overridden by the user; | |
2018 | see the I<-logfile> command-line option in L</"COMMAND-LINE OPTIONS"> below. | |
2019 | If this log file already exists, B<autoinst> will append its data to the end | |
2020 | rather than overwrite it. | |
2021 | Use the I<-verbose> command-line option to ask for more detailed info. | |
2022 | 1882 | |
2023 | 1883 | |
2024 | 1884 | =head2 A note for MiKTeX users |
2153 | 2013 | |
2154 | 2014 | =head2 NFSS codes |
2155 | 2015 | |
2156 | I<< B<CAVEAT>: this functionality was almost completely rewritten | |
2157 | in release 2019-03-14. | |
2016 | I<< B<CAVEAT>: this functionality was almost completely rewritten in release 2019-03-14. | |
2158 | 2017 | Older versions tried to map all fonts directly to short NFSS codes, |
2159 | 2018 | but often had to invent non-standard codes in order to deal with the |
2160 | 2019 | many different weights and widths that occur in the wild. |
2161 | Such non-standard NFSS codes will no longer | |
2020 | These non-standard NFSS codes used by older versions of B<autoinst> will no longer | |
2162 | 2021 | work for fonts installed with newer versions; for those you'll have to either |
2163 | 2022 | use the long names or stick to the standard NFSS codes. |
2164 | (This change mainly concerns very light or very heavy weights | |
2165 | and very condensed widths; | |
2166 | for more moderate weights and widths, | |
2167 | existing code will very probably continue to work.) | |
2023 | This change mainly concerns very light or very heavy weights and very condensed widths; | |
2024 | for more moderate weights and widths, existing code will very probably continue to work. | |
2168 | 2025 | >> |
2169 | 2026 | |
2170 | 2027 | LaTeX's New Font Selection System (NFSS) |
2171 | 2028 | identifies fonts by a combination of family, |
2172 | 2029 | series (the concatenation of weight and width), shape and size. |
2173 | B<autoinst> parses the font's metadata | |
2174 | (more precisely: the output of C<otfinfo --info>) | |
2030 | B<autoinst> parses the font's metadata (more precisely: the output of C<otfinfo --info>) | |
2175 | 2031 | to determine these parameters. |
2176 | When this fails (usually because the font family contains uncommon weights, | |
2177 | widths or shapes), | |
2032 | When this fails (usually because the font family contains uncommon weights, widths | |
2033 | or shapes), | |
2178 | 2034 | B<autoinst> ends up with different fonts having the I<same> values |
2179 | 2035 | for these font parameters; such fonts cannot be used in NFSS, |
2180 | 2036 | since there's no way distinguish them. |
2181 | When B<autoinst> detects such a situation, it will print an error message | |
2182 | and abort. | |
2037 | When B<autoinst> detects such a situation, it will print an error message and abort. | |
2183 | 2038 | If that happens, either rerun B<autoinst> on a smaller set of fonts, |
2184 | or add the missing widths, weights and shapes to the tables C<NFSS_WIDTH>, | |
2185 | C<NFSS_WEIGHT> and C<NFSS_SHAPE>, near the top of the source code. | |
2039 | or add the missing widths, weights and shapes to the tables C<%NFSS_WIDTH>, | |
2040 | C<%NFSS_WEIGHT> and C<%NFSS_SHAPE>, near the top of the source code. | |
2186 | 2041 | Please also send a bug report (see L<AUTHOR> below). |
2187 | 2042 | |
2188 | 2043 | The mapping of shapes to NFSS codes is done using the following table: |
2193 | 2048 | Italic, Cursive, Kursive it |
2194 | 2049 | Oblique, Slant(ed), Incline(d) sl |
2195 | 2050 | |
2196 | (I<Exception:> Adobe Silentium Pro contains two Roman shapes; | |
2197 | we map the first of these to "n", for the second one we (ab)use the "it" code | |
2198 | as this family doesn't contain an Italic shape.) | |
2199 | ||
2200 | The mapping of weights and widths to NFSS codes is a more complex, | |
2201 | two-step proces. | |
2051 | (I<Exception:> Adobe Silentium Pro contains two Roman shapes; we map the first of these | |
2052 | to "n", for the second one we [ab]use the "it" code as this family doesn't contain | |
2053 | an Italic shape.) | |
2054 | ||
2055 | The mapping of weights and widths to NFSS code is a more complex, two-step proces. | |
2202 | 2056 | In the first step, all fonts are assigned a "series" name that is simply |
2203 | the concatenation of its weight and width | |
2204 | (after expanding any abbreviations and converting to lowercase). | |
2205 | A font with "Cond" width and "Ultra" weight will then be known | |
2206 | as "ultrablackcondensed". | |
2057 | the concatenation of its full weight and width (after expanding any abbreviations | |
2058 | and converting to lowercase). | |
2059 | So a font with "Cond" width and "Ultra" weight will be known as "ultrablackcondensed". | |
2207 | 2060 | |
2208 | 2061 | In the second step, B<autoinst> tries to map all combinations of NFSS codes |
2209 | 2062 | (ul, el, l, sl, m, sb, b, eb and ub for weights; |
2210 | 2063 | uc, ec, c, sc, m, sx, x, ex and ux for widths) to actual fonts. |
2211 | Of course, not all 81 combinations of these NFSS weights and widths will map | |
2212 | to existing fonts; | |
2213 | and conversely it may not be possible to assign every existing font | |
2064 | Of course, not all 81 combinations of these NFSS weights and widths will map to | |
2065 | existing fonts; and conversely it may not be possible to assign every existing font | |
2214 | 2066 | a unique code in a sane way (especially on the weight axis, some font families |
2215 | 2067 | offer more choices or finer granularity than NFSS's codes can handle; |
2216 | 2068 | e.g., Fira Sans contains fifteen(!) different weights, |
2217 | 2069 | including an additional "Medium" weight between Regular and Semibold). |
2218 | 2070 | |
2219 | B<autoinst> tries hard to ensure that the most common NFSS codes | |
2220 | (and high-level commands such as C<\bfseries>, | |
2221 | which are built on top of those codes) will "just work". | |
2222 | ||
2223 | To see exactly which NFSS codes map to which fonts, see the log file | |
2224 | (pro tip: run B<autoinst> with the I<-dryrun> option | |
2225 | to check the chosen mapping beforehand). | |
2226 | The I<-nfssweight> and I<-nfsswidth> command-line options can be used | |
2227 | to finetune the mapping between NFSS codes and fonts. | |
2228 | ||
2229 | To access specific weights or widths, | |
2230 | one can always use the C<\fontseries> command with the full series name | |
2231 | (i.e., C<\fontseries{demibold}\selectfont>). | |
2071 | This mapping between NFSS codes and actual fonts is based on a few principles: | |
2072 | ||
2073 | =over 4 | |
2074 | ||
2075 | =item B<Usefulness>. As many of the most commonly used NFSS codes as possible | |
2076 | should point to actual fonts. | |
2077 | ||
2078 | =item B<Exactness>. Exact matches always win: if the font family contains | |
2079 | a Semibold Condensed font, that's what the "sbc" code will map to. | |
2080 | ||
2081 | =item B<Sanity>. A code like "sb" will always map to something semi-boldish. | |
2082 | If there's no Semibold font it might map to Demibold or Medium, | |
2083 | but never to Black. If there is no close match, the NFSS code will simply not be used. | |
2084 | ||
2085 | =item B<Well-ordering>. The mapping respects the ordering that is inherent in | |
2086 | the NFSS codes, so "sb" will be heavier than "m" and lighter than "b". | |
2087 | ||
2088 | =item B<Uniqueness>. No two NFSS codes will map to the same font (with the exception | |
2089 | of "bx"; since this is so ubiquitous in Latex, B<autoinst> will treat it as a synonym | |
2090 | for "b" if there is no BoldExtended font). | |
2091 | ||
2092 | =back | |
2093 | ||
2094 | These rules should ensure that the standard NFSS codes (and high-level commands | |
2095 | such as C<\bfseries>, which are built on top of these codes) will "just work". | |
2096 | To access specific weights or widths, use the C<\fontseries> command with | |
2097 | the full series name (i.e., C<\fontseries{demibold}\selectfont>). | |
2098 | ||
2099 | To see exactly which NFSS codes map to which fonts, please refer to | |
2100 | the generated F<fd> files. | |
2232 | 2101 | |
2233 | 2102 | |
2234 | 2103 | =head1 COMMAND-LINE OPTIONS |
2247 | 2116 | |
2248 | 2117 | =item B<-dryrun> |
2249 | 2118 | |
2250 | Don't generate output; just parse input fonts and write | |
2251 | a log file saying what it would have done. | |
2252 | ||
2253 | =item B<-logfile>=I<filename> | |
2254 | ||
2255 | Write log data to F<filename> instead of the default F<< <fontfamily>.log >>. | |
2256 | If the file already exist, B<autoinst> appends to it; | |
2257 | it doesn't overwrite an existing file. | |
2258 | ||
2259 | =item B<-verbose> | |
2260 | ||
2261 | Add more details to the log file. Repeat this option for even more info. | |
2119 | Don't generate any output files; only parse the input fonts and create | |
2120 | F<autoinst.log> showing which fonts would have been generated. | |
2262 | 2121 | |
2263 | 2122 | =item B<-encoding>=I<encoding[,encoding]> |
2264 | 2123 | |
2265 | Generate the specified encoding(s) for the text fonts. | |
2266 | Multiple encodings may be specified as a comma-separated list: | |
2267 | C<-encoding=OT1,T1,LY1> (without spaces!). | |
2268 | The style file passes these to F<fontenc> in the specified order, | |
2269 | so the I<last> one will become the default text encoding of your document. | |
2124 | Generate the specified encoding(s) for the text fonts. Multiple text encodings may be | |
2125 | specified as a comma-separated list: C<-encoding=OT1,T1,LY1> (without spaces!). | |
2126 | The generated style file passes these encodings to F<fontenc> in the specified order, | |
2127 | so the last one will become the default text encoding for your document. | |
2270 | 2128 | |
2271 | 2129 | The default choice of encodings is "OT1,T1,LY1". |
2272 | 2130 | For each encoding, a file F<< <encoding>.enc >> (in all I<lowercase>!) |
2281 | 2139 | if the text encodings (see I<-encoding> above) include T1, |
2282 | 2140 | B<-nots1> otherwise. |
2283 | 2141 | |
2284 | =item B<-serif>, B<-sanserif>, B<-typewriter> | |
2285 | ||
2286 | Install the font as a serif, sanserif or typewriter font, respectively. | |
2287 | This changes how you access the font in LaTeX: with C<\rmfamily>/C<\textrm>, | |
2288 | C<\sffamily>/C<\textsf> or C<\ttfamily>/C<\texttt>. | |
2142 | =item B<-sanserif> | |
2143 | ||
2144 | Install the font as a sanserif font, accessed via C<\sffamily> and C<\textsf>. | |
2289 | 2145 | The generated style file redefines C<\familydefault>, |
2290 | 2146 | so including it will still make this font the default text font. |
2291 | 2147 | |
2148 | =item B<-typewriter> | |
2149 | ||
2150 | Install the font as a typewriter font, accessed via C<\ttfamily> and | |
2151 | C<\texttt>. | |
2152 | The generated style file redefines C<\familydefault>, | |
2153 | so including it will still make this font the default text font. | |
2154 | ||
2292 | 2155 | =item B<-lining> / B<-nolining> |
2293 | 2156 | |
2294 | 2157 | Control the creation of fonts with lining figures. The default is |
2320 | 2183 | |
2321 | 2184 | =item B<-titling> / B<-notitling> |
2322 | 2185 | |
2323 | Control the creation of titling families. The default is B<-titling>. | |
2186 | Control the creation of titling fonts. The default is B<-titling>. | |
2324 | 2187 | |
2325 | 2188 | =item B<-superiors> / B<-nosuperiors> |
2326 | 2189 | |
2338 | 2201 | in the list "subs", "sinf" or "dnom" that is supported by the fonts. |
2339 | 2202 | The default value is "none". |
2340 | 2203 | |
2341 | I<< If you specify a style of inferiors that isn't present in the font, | |
2342 | B<autoinst> will fall back to its default behaviour of not creating fonts | |
2343 | with inferiors at all; it won't try to substitute one of the other styles. >> | |
2204 | I<< Note that if you specify a style of inferiors that isn't | |
2205 | present in the font, B<autoinst> silently falls back to its default behaviour | |
2206 | of not creating fonts with inferiors; it doesn't try to substitute one of | |
2207 | the other features. >> | |
2344 | 2208 | |
2345 | 2209 | =item B<-fractions> / B<-nofractions> |
2346 | 2210 | |
2347 | 2211 | Control the creation of fonts with numerators and denominators. |
2348 | 2212 | The default is B<-nofractions>. |
2349 | 2213 | |
2350 | =item B<-ligatures> / B<-noligatures> | |
2351 | ||
2352 | Some fonts create glyphs for the standard f-ligatures (ff, fi, fl, ffi, ffl), | |
2353 | but don't provide a "liga" feature to access these. | |
2354 | This option tells B<autoinst> to add extra C<LIGKERN> rules to | |
2355 | the generated fonts to enable the use of these ligatures. | |
2356 | Since this option is rarely necessary | |
2357 | (most fonts with f-ligatures do provide the matching "liga" feature), | |
2358 | the default is B<-noligatures>. | |
2214 | =item B<-ornaments> / B<-noornaments> | |
2215 | ||
2216 | Control the creation of ornament fonts. The default is B<-ornaments>. | |
2359 | 2217 | |
2360 | 2218 | =item B<-defaultlining> / B<-defaultoldstyle> |
2361 | 2219 | |
2382 | 2240 | |
2383 | 2241 | =item B<-mergewidths> / B<-nomergewidths> |
2384 | 2242 | |
2385 | Some font families put their Condensed, Narrow, Extended etc. widths | |
2386 | in separate families; | |
2387 | this option tells B<autoinst> to merge those separate families into | |
2388 | the main family. | |
2389 | The default is B<-mergewidths>. | |
2390 | ||
2391 | =item B<-mergesmallcaps> / B<-nomergesmallcaps> | |
2392 | ||
2393 | Even more annoyingly, some font families put their small caps fonts | |
2394 | in a separate family; | |
2395 | this option tells B<autoinst> to merge the small caps fonts into | |
2396 | the main family. | |
2397 | The default is B<-mergesmallcaps>. | |
2398 | ||
2399 | =item B<-nfssweight>=I<code>=I<weight>, B<-nfsswidth>=I<code>=I<width> | |
2400 | ||
2401 | Map the NFSS code I<code> to the given weight or width, | |
2402 | overriding the built-in tables. | |
2403 | Each of these options may be given multiple times, | |
2404 | to override more than one NFSS code. | |
2405 | Example: to map the "ul" code to the "Thin" weight, use C<-nfssweight=ul=thin>. | |
2406 | To inhibit the use of the "ul" code completely, use C<-nfssweight=ul=>. | |
2243 | Some font families put Condensed, Narrow, Extended etc. fonts in separate families; | |
2244 | this option tells B<autoinst> to merge those separate families into the main family. | |
2245 | The default is B<-nomergewidths>. | |
2407 | 2246 | |
2408 | 2247 | =item B<-extra>=I<text> |
2409 | 2248 | |
2414 | 2253 | =item B<-manual> |
2415 | 2254 | |
2416 | 2255 | Manual mode; for users who want to post-process the generated files and commands. |
2417 | By default, B<autoinst> immediately executes all F<otftotfm> commands | |
2418 | it generates; | |
2256 | By default, B<autoinst> immediately executes all F<otftotfm> commands it generates; | |
2419 | 2257 | in manual mode, these are instead written to a file F<autoinst.bat>. |
2420 | 2258 | Furthermore it tells F<otftotfm> to generate human readable (and editable) |
2421 | 2259 | F<pl/vpl> files instead of the default F<tfm/vf> ones, |
2433 | 2271 | =item B<-> move all generated files to a proper TEXMF tree, |
2434 | 2272 | and, if necessary, update the filename database; |
2435 | 2273 | |
2436 | =item B<-> tell TeX about the new F<map> file | |
2437 | (usually by running C<updmap> or similar). | |
2274 | =item B<-> tell TeX about the new F<map> file (usually by running C<updmap> or similar). | |
2438 | 2275 | |
2439 | 2276 | =back |
2440 | 2277 | |
2496 | 2333 | |
2497 | 2334 | Marc Penninga (F<marcpenninga@gmail.com>) |
2498 | 2335 | |
2499 | When sending a bug report, please give as much relevant information as possible; | |
2500 | this usually includes (but may not be limited to) the log file | |
2501 | (please add the I<-verbose> command-line option, for extra info). | |
2502 | If you see any error messages, please include these I<verbatim>; | |
2503 | don't paraphase. | |
2336 | When sending a bug report, please give as much relevant information as | |
2337 | possible. | |
2338 | If you see any error messages | |
2339 | (whether from B<autoinst> itself, from the I<LCDF TypeTools>, from Perl | |
2340 | or from the OS), include these I<verbatim>; don't paraphrase. | |
2504 | 2341 | |
2505 | 2342 | |
2506 | 2343 | =head1 COPYRIGHT |
2533 | 2370 | |
2534 | 2371 | =over 12 |
2535 | 2372 | |
2536 | =item I<2019-04-22> | |
2537 | ||
2538 | Fixed a bug in the generation of swash shapes. | |
2539 | ||
2540 | =item I<2019-04-19> | |
2541 | ||
2542 | Fixed a bug that affected -mergesmallcaps with multiple encodings. | |
2543 | ||
2544 | =item I<2019-04-16> | |
2545 | ||
2546 | Added the <-mergesmallcaps> option, to handle cases where | |
2547 | the small caps fonts are in separate font families. | |
2548 | Titling shape is now treated as a separate family instead of a distinct shape; | |
2549 | it is generated only for fonts with the 'titl' feature. | |
2550 | Only add f-ligatures to fonts when explicitly asked to (<-fligatures>). | |
2551 | ||
2552 | =item I<2019-04-11> | |
2553 | ||
2554 | Tried to make the log file more relevant. | |
2555 | Added the I<-nfssweight> and I<-nfsswidth> options, | |
2556 | and finetuned the automatic mapping between fonts and NFSS codes. | |
2557 | Changed the name of the generated log file to F<< <fontfamily>.log >>, | |
2558 | and revived the I<-logfile> option to allow overriding this choice. | |
2559 | Made I<-mergewidths> the default (instead of I<-nomergewidths>). | |
2560 | ||
2561 | 2373 | =item I<2019-04-01> |
2562 | 2374 | |
2563 | 2375 | Fine-tuned the decision where to put generated files; |
2568 | 2380 | put all generated files into a subdirectory C<./autoinst_output/> |
2569 | 2381 | instead of all over the current working directory. |
2570 | 2382 | |
2571 | Added "auto" value to the I<inferiors> option, | |
2383 | Added to "auto" value to the I<inferiors> option, | |
2572 | 2384 | to tell B<autoinst> to use whatever inferior characters are available. |
2573 | 2385 | |
2574 | =item I<2019-03-14> | |
2575 | ||
2576 | (never released to CTAN) | |
2386 | =item I<2019-03-14> (never released to CTAN) | |
2577 | 2387 | |
2578 | 2388 | Overhauled the mapping of fonts (more specifically of weights and widths; |
2579 | the mapping of shapes didn't change) to NFSS codes. | |
2580 | Instead of inventing our own codes to deal with every possible weight | |
2581 | and width out there, we now create "long" codes based on the names | |
2582 | in the font metadata. | |
2583 | Then we add "ssub" rules to the F<fd> files to map the standard NFSS codes | |
2584 | to our fancy names (see the section B<NFSS codes>; | |
2389 | the mapping of shapes didn't change) to NFSS codes. Instead of inventing our own codes | |
2390 | to deal with every possible weight and width out there, we now create "long" codes | |
2391 | based on the names in the font metadata. Then we add "ssub" rules to the F<fd> | |
2392 | files to map the standard NFSS codes to our fancy names (see the section B<NFSS codes>; | |
2585 | 2393 | based on discussions with Frank Mittelbach and Bob Tennent). |
2586 | 2394 | |
2587 | 2395 | =item I<2018-08-10> |
2624 | 2432 | |
2625 | 2433 | =item I<2015-11-22> |
2626 | 2434 | |
2627 | Bugfix: LaTeX doesn't like command names with dashes in it. | |
2435 | Bugfix: Latex doesn't like command names with dashes in it. | |
2628 | 2436 | |
2629 | 2437 | =item I<2015-05-13> |
2630 | 2438 |
3 | 3 | |
4 | 4 | ---------------------------------------------------------------------------- |
5 | 5 | |
6 | Copyright (C) 2005-2019 Marc Penninga. | |
6 | Copyright (C) 2005-2013 Marc Penninga. | |
7 | 7 | |
8 | 8 | This program is free software; you can redistribute it and/or |
9 | 9 | modify it under the terms of the GNU General Public License |
33 | 33 | use warnings; |
34 | 34 | |
35 | 35 | use integer; |
36 | use Getopt::Long (); | |
37 | 36 | use List::Util @List::Util::EXPORT_OK; |
38 | 37 | use Pod::Usage; |
39 | 38 | |
40 | our ($NUM_GLYPHS, $UNITS_PER_EM, %kern); | |
39 | our ($NUM_GLYPHS, $UNITS_PER_EM, %KPX); | |
41 | 40 | |
42 | 41 | sub main { |
43 | %ARGV = ( | |
44 | print_func => \&print_kpx, | |
45 | ); | |
46 | ||
47 | Getopt::Long::GetOptions( | |
48 | 'help|?' => sub { pod2usage(-verbose => 0); }, | |
49 | 'doc' => sub { pod2usage(-verbose => 2); }, | |
50 | 'afm' => sub { $ARGV{print_func} = \&print_kpx; }, | |
51 | 'kpx' => sub { $ARGV{print_func} = \&print_kpx; }, | |
52 | 'lua' => sub { $ARGV{print_func} = \&print_lua; }, | |
53 | ) or pod2usage(-verbose => 0); | |
54 | 42 | pod2usage(-verbose => 0) if @ARGV != 1; |
55 | 43 | |
56 | 44 | my %font = OTF::get_tables($ARGV[0]); |
76 | 64 | |
77 | 65 | for my $subtable (@subtables) { |
78 | 66 | my $pos_format = unpack 'n', $subtable; |
79 | if ($pos_format == 1) { | |
67 | if ($pos_format == 1) { | |
80 | 68 | OTF::GPOS::parse_pos_format_1($subtable); |
81 | 69 | } |
82 | 70 | elsif ($pos_format == 2) { |
88 | 76 | } |
89 | 77 | } |
90 | 78 | |
91 | &{$ARGV{print_func}}( \%kern, \@glyph_name ); | |
79 | my $num_kernpairs = sum map { scalar keys %{$KPX{$_}} } keys %KPX; | |
80 | print "StartKernData\nStartKernPairs $num_kernpairs\n"; | |
81 | for my $first (sort { $a <=> $b } keys %KPX) { | |
82 | my $first_glyph = $glyph_name[$first]; | |
83 | for my $second (sort { $a <=> $b } keys %{$KPX{$first}}) { | |
84 | print "KPX $first_glyph $glyph_name[$second] ", | |
85 | "$KPX{$first}{$second}\n"; | |
86 | } | |
87 | } | |
88 | print "EndKernPairs\nEndKernData\n"; | |
89 | ||
92 | 90 | return; |
93 | 91 | } |
94 | 92 | |
95 | # ------------------------------------------------------------------------ | |
96 | # Print kerning data in Adobe's KPX format | |
97 | # ------------------------------------------------------------------------ | |
98 | sub print_kpx { | |
99 | my %kern = %{ shift @_; }; | |
100 | my @glyph = @{ shift @_; }; | |
101 | ||
102 | my $num_kernpairs = sum map { scalar keys %{$kern{$_}} } keys %kern; | |
103 | print "StartKernData\nStartKernPairs $num_kernpairs\n"; | |
104 | for my $l (sort { $glyph[$a] cmp $glyph[$b] } keys %kern) { | |
105 | my $l_glyph = $glyph[$l]; | |
106 | for my $r (sort { $glyph[$a] cmp $glyph[$b] } keys %{$kern{$l}}) { | |
107 | print "KPX $l_glyph $glyph[$r] ", | |
108 | "$kern{$l}{$r}\n"; | |
109 | } | |
110 | } | |
111 | print "EndKernPairs\nEndKernData\n"; | |
112 | } | |
113 | ||
114 | # ------------------------------------------------------------------------ | |
115 | # Print kerning data as a Luatex custom font feature | |
116 | # ------------------------------------------------------------------------ | |
117 | sub print_lua { | |
118 | my %kern = %{ shift @_; }; | |
119 | my @glyph = @{ shift @_; }; | |
120 | ||
121 | print <<'END_FEATURE_PREFIX'; | |
122 | fonts.handlers.otf.addfeature { | |
123 | name = 'kern', | |
124 | type = 'kern', | |
125 | data = { | |
126 | END_FEATURE_PREFIX | |
127 | ||
128 | for my $l ( sort { $glyph[$a] cmp $glyph[$b] } keys %kern ) { | |
129 | print ' ' x 8, "[ '$glyph[$l]' ] = {"; | |
130 | for my $r ( sort { $glyph[$a] cmp $glyph[$b] } keys %{$kern{$l}} ) { | |
131 | print "\n", ' ' x 12, "[ '$glyph[$r]' ] = $kern{$l}{$r},"; | |
132 | } | |
133 | print " },\n"; | |
134 | } | |
135 | ||
136 | print <<'END_FEATURE_POSTFIX'; | |
137 | } | |
138 | } | |
139 | END_FEATURE_POSTFIX | |
140 | } | |
141 | 93 | |
142 | 94 | ######################################################################## |
143 | 95 | |
514 | 466 | } |
515 | 467 | |
516 | 468 | #----------------------------------------------------------------------- |
517 | # Parse subtable in PairPosFormat 1, store kern pairs in global %kern | |
469 | # Parse subtable in PairPosFormat 1, store kern pairs in global %KPX | |
518 | 470 | #----------------------------------------------------------------------- |
519 | 471 | sub parse_pos_format_1 { |
520 | 472 | my $subtable = shift; |
542 | 494 | my ($second, $value) |
543 | 495 | = unpack "n\@${value_offset}s>", $pair_value_record; |
544 | 496 | next if $value == 0; |
545 | $kern{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM; | |
497 | $KPX{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM; | |
546 | 498 | } |
547 | 499 | } |
548 | 500 | |
550 | 502 | } |
551 | 503 | |
552 | 504 | #----------------------------------------------------------------------- |
553 | # Parse subtable in PairPosFormat 2, store kern pairs in global %kern | |
505 | # Parse subtable in PairPosFormat 2, store kern pairs in global %KPX | |
554 | 506 | #----------------------------------------------------------------------- |
555 | 507 | sub parse_pos_format_2 { |
556 | 508 | my $subtable = shift; |
587 | 539 | |
588 | 540 | for my $first (@first) { |
589 | 541 | for my $second (@second) { |
590 | $kern{$first}{$second} ||= $value; | |
542 | $KPX{$first}{$second} ||= $value; | |
591 | 543 | } |
592 | 544 | } |
593 | 545 | } |
678 | 630 | package OTF::Kern; |
679 | 631 | |
680 | 632 | #----------------------------------------------------------------------- |
681 | # Parse "kern"table, store kern pairs in global %kern | |
633 | # Parse "kern"table, store kern pairs in global %KPX | |
682 | 634 | #----------------------------------------------------------------------- |
683 | 635 | sub parse_kerntable { |
684 | 636 | my $kern = shift; |
700 | 652 | my ($first, $second, $value) = unpack 'nns>', $kern_pair; |
701 | 653 | next if $value == 0; |
702 | 654 | |
703 | $kern{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM; | |
655 | $KPX{$first}{$second} ||= 1000 * $value / $UNITS_PER_EM; | |
704 | 656 | } |
705 | 657 | } |
706 | 658 | |
735 | 687 | |
736 | 688 | =head1 SYNOPSIS |
737 | 689 | |
738 | B<ot2kpx> [ I<-afm> | I<-kpx> | I<-lua> ] B<fontfile> | |
690 | =over 8 | |
691 | ||
692 | =item B<ot2kpx> | |
693 | ||
694 | B<fontfile> | |
695 | ||
696 | =back | |
739 | 697 | |
740 | 698 | |
741 | 699 | =head1 DESCRIPTION |
742 | 700 | |
743 | B<ot2kpx> extract the kerning data from OpenType fonts and prints it | |
744 | to C<stdout>, either in Adobe's KPX format (for adding to an F<afm> file) | |
745 | or as a Luatex custom feature, for use with the C<\directlua> command. | |
701 | B<ot2kpx> extract the kerning data from OpenType fonts (both F<otf> | |
702 | and F<ttf> formats) and prints it (in F<afm> format) to C<stdout>. | |
746 | 703 | |
747 | 704 | |
748 | 705 | =head1 OPTIONS AND ARGUMENTS |
749 | 706 | |
750 | 707 | =over 4 |
751 | 708 | |
752 | =item B<-afm>, B<-kpx> | |
753 | ||
754 | Output the kerning data in Adobe's KPX format, as used in F<afm> files. | |
755 | This is the default output format. | |
756 | ||
757 | =item B<-lua> | |
758 | ||
759 | Output the kerning data as a Luatex custom font feature, | |
760 | to be included in a C<\directlua> command. | |
761 | ||
762 | 709 | =item B<fontfile> |
763 | 710 | |
764 | The OpenType font (both F<otf> and F<ttf> format are supported). | |
711 | The OpenType font (in either F<otf> or F<ttf> format). | |
765 | 712 | |
766 | 713 | =back |
767 | 714 | |
823 | 770 | |
824 | 771 | =head1 COPYRIGHT |
825 | 772 | |
826 | Copyright (C) 2005-2019 Marc Penninga. | |
773 | Copyright (C) 2005-2013 Marc Penninga. | |
827 | 774 | |
828 | 775 | |
829 | 776 | =head1 LICENSE |
850 | 797 | |
851 | 798 | =over 12 |
852 | 799 | |
853 | =item I<2019-04-15> | |
854 | ||
855 | Added the -lua command-line option to get output in Luatex's | |
856 | custom feature format. | |
857 | ||
858 | 800 | =item I<2013-08-07> |
859 | 801 | |
860 | 802 | Replaced all C<given/when> constructions in the source code by C<if>'s, |
0 | 0 | #!/usr/bin/env perl |
1 | # latexindent.pl, version 3.6, 2019-05-05 | |
1 | # latexindent.pl, version 3.5.3, 2018-10-13 | |
2 | 2 | # |
3 | 3 | # This program is free software: you can redistribute it and/or modify |
4 | 4 | # it under the terms of the GNU General Public License as published by |
1 | 1 | |
2 | 2 | -- Copyright 2016-2018 Brian Dunn |
3 | 3 | |
4 | printversion = "v0.71" | |
4 | printversion = "v0.70" | |
5 | 5 | requiredconfversion = "2" -- also at *lwarpmk.conf |
6 | 6 | |
7 | 7 | function printhelp () |
77 | 77 | -- printconf () ; |
78 | 78 | os.exit(1) ; |
79 | 79 | end |
80 | ||
81 | function printhowtorecompile () | |
82 | -- Tells the user how to recompile to regenerate the configuration files. | |
83 | print ("lwarpmk: The configuration files lwarpmk.conf and "..sourcename..".lwarpmkconf" ) | |
84 | print ("lwarpmk: must be updated. To do so, recompile" ) | |
85 | print ("lwarpmk: " , sourcename..".tex" ) | |
86 | if ( printlatexcmd == "" ) then | |
87 | print ("lwarpmk: using xe/lua/pdflatex," ) | |
88 | else | |
89 | print ("lwarpmk: using the command:") | |
90 | print ("lwarpmk: " , printlatexcmd ) | |
91 | end | |
92 | print ("lwarpmk: then use lwarpmk again.") | |
93 | end -- printhowtorecompile | |
94 | 80 | |
95 | 81 | function ignoreconf () |
96 | 82 | -- Global argument index |
253 | 239 | if ( (package.config:sub(1,1)) ~= dirslash ) then |
254 | 240 | print ("lwarpmk: ===") |
255 | 241 | print ("lwarpmk: It appears that lwarpmk.conf is for a different operating system." ) |
256 | printhowtorecompile () | |
257 | print ("lwarpmk: ===") | |
258 | os.exit(1) | |
242 | print ("lwarpmk: To adjust lwarpmk.conf for the current operating system," ) | |
243 | print ("lwarpmk: recompile the original document using xe/lua/pdflatex." ) | |
244 | print ("lwarpmk: ") | |
245 | print ("lwarpmk: lwarpmk shall attempt to continue...") | |
246 | print ("lwarpmk: ===") | |
259 | 247 | end |
260 | 248 | -- Error if the configuration file's version is not current: |
261 | 249 | if ( confversion ~= requiredconfversion ) then |
262 | 250 | print ("lwarpmk: ===") |
263 | printhowtorecompile () | |
251 | print ("lwarpmk: The configuration files lwarpmk.conf and "..sourcename..".lwarpmkconf" ) | |
252 | print ("lwarpmk: must be updated. To update the configuration files," ) | |
253 | print ("lwarpmk: recompile "..sourcename..".tex using xe/lua/pdflatex," ) | |
254 | print ("lwarpmk: then use lwarpmk again.") | |
264 | 255 | print ("lwarpmk: ===") |
265 | 256 | os.exit(1) |
266 | 257 | end |
564 | 555 | -- |
565 | 556 | -- See if the document must be recompiled first: |
566 | 557 | checklimages () |
567 | -- See if the HTML version exists: | |
558 | -- See if the print version exists: | |
568 | 559 | checkhtmlpdfexists () |
569 | 560 | -- Attempt to create the lateximages: |
570 | 561 | print ("lwarpmk: Creating lateximages.") |
17748 | 17748 | |
17749 | 17749 | |
17750 | 17750 | |
17751 | $as_echo "#define TL_VERSION \"TeX Live 2020/dev\"" >>confdefs.h | |
17751 | $as_echo "#define TL_VERSION \"TeX Live 2019\"" >>confdefs.h | |
17752 | 17752 | |
17753 | 17753 | |
17754 | 17754 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking if C99 variadic macros are supported" >&5 |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for Web2C 2020/dev. | |
2 | # Generated by GNU Autoconf 2.69 for Web2C 2019. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-k@tug.org>. |
5 | 5 | # |
589 | 589 | # Identity of this package. |
590 | 590 | PACKAGE_NAME='Web2C' |
591 | 591 | PACKAGE_TARNAME='web2c' |
592 | PACKAGE_VERSION='2020/dev' | |
593 | PACKAGE_STRING='Web2C 2020/dev' | |
592 | PACKAGE_VERSION='2019' | |
593 | PACKAGE_STRING='Web2C 2019' | |
594 | 594 | PACKAGE_BUGREPORT='tex-k@tug.org' |
595 | 595 | PACKAGE_URL='' |
596 | 596 | |
1613 | 1613 | # Omit some internal or obsolete options to make the list less imposing. |
1614 | 1614 | # This message is too long to be a string in the A/UX 3.1 sh. |
1615 | 1615 | cat <<_ACEOF |
1616 | \`configure' configures Web2C 2020/dev to adapt to many kinds of systems. | |
1616 | \`configure' configures Web2C 2019 to adapt to many kinds of systems. | |
1617 | 1617 | |
1618 | 1618 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1619 | 1619 | |
1687 | 1687 | |
1688 | 1688 | if test -n "$ac_init_help"; then |
1689 | 1689 | case $ac_init_help in |
1690 | short | recursive ) echo "Configuration of Web2C 2020/dev:";; | |
1690 | short | recursive ) echo "Configuration of Web2C 2019:";; | |
1691 | 1691 | esac |
1692 | 1692 | cat <<\_ACEOF |
1693 | 1693 | |
1908 | 1908 | test -n "$ac_init_help" && exit $ac_status |
1909 | 1909 | if $ac_init_version; then |
1910 | 1910 | cat <<\_ACEOF |
1911 | Web2C configure 2020/dev | |
1911 | Web2C configure 2019 | |
1912 | 1912 | generated by GNU Autoconf 2.69 |
1913 | 1913 | |
1914 | 1914 | Copyright (C) 2012 Free Software Foundation, Inc. |
2997 | 2997 | This file contains any messages produced by compilers while |
2998 | 2998 | running configure, to aid debugging if configure makes a mistake. |
2999 | 2999 | |
3000 | It was created by Web2C $as_me 2020/dev, which was | |
3000 | It was created by Web2C $as_me 2019, which was | |
3001 | 3001 | generated by GNU Autoconf 2.69. Invocation command line was |
3002 | 3002 | |
3003 | 3003 | $ $0 $@ |
3378 | 3378 | |
3379 | 3379 | |
3380 | 3380 | |
3381 | WEB2CVERSION=2020/dev | |
3381 | WEB2CVERSION=2019 | |
3382 | 3382 | |
3383 | 3383 | |
3384 | 3384 | am__api_version='1.16' |
8687 | 8687 | |
8688 | 8688 | # Define the identity of the package. |
8689 | 8689 | PACKAGE='web2c' |
8690 | VERSION='2020/dev' | |
8690 | VERSION='2019' | |
8691 | 8691 | |
8692 | 8692 | |
8693 | 8693 | cat >>confdefs.h <<_ACEOF |
23622 | 23622 | Report bugs to <bug-libtool@gnu.org>." |
23623 | 23623 | |
23624 | 23624 | lt_cl_version="\ |
23625 | Web2C config.lt 2020/dev | |
23625 | Web2C config.lt 2019 | |
23626 | 23626 | configured by $0, generated by GNU Autoconf 2.69. |
23627 | 23627 | |
23628 | 23628 | Copyright (C) 2011 Free Software Foundation, Inc. |
27051 | 27051 | # report actual input values of CONFIG_FILES etc. instead of their |
27052 | 27052 | # values after options handling. |
27053 | 27053 | ac_log=" |
27054 | This file was extended by Web2C $as_me 2020/dev, which was | |
27054 | This file was extended by Web2C $as_me 2019, which was | |
27055 | 27055 | generated by GNU Autoconf 2.69. Invocation command line was |
27056 | 27056 | |
27057 | 27057 | CONFIG_FILES = $CONFIG_FILES |
27121 | 27121 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
27122 | 27122 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
27123 | 27123 | ac_cs_version="\\ |
27124 | Web2C config.status 2020/dev | |
27124 | Web2C config.status 2019 | |
27125 | 27125 | configured by $0, generated by GNU Autoconf 2.69, |
27126 | 27126 | with options \\"\$ac_cs_config\\" |
27127 | 27127 |
0 | 2019-05-03 Akira Kakuto <kakuto@w32tex.org> | |
1 | ||
2 | * pdftosrc-poppler0.76.0.cc, pdftoepdf-poppler0.76.0.cc: | |
3 | Added to support system poppler 0.76.[01]. | |
4 | ||
5 | 0 | 2019-04-07 Karl Berry <karl@freefriends.org> |
6 | 1 | |
7 | 2 | * TeX Live 2019. |
27 | 27 | Provide new files: |
28 | 28 | pdftosrc-newpoppler.cc for poppler-0.59.0 upto poppler-0.70.1. |
29 | 29 | pdftosrc-poppler0.71.0 for poppler-0.71.0. |
30 | pdftosrc-poppler0.72.0 for poppler-0.72.0 upto poppler-0.75.0. | |
31 | pdftosrc-poppler0.76.0 for poppler-0.76.0 and newer. | |
30 | pdftosrc-poppler0.72.0 for poppler-0.72.0 and newer. | |
32 | 31 | pdftoepdf-poppler0.68.0.cc for poppler-0.59.0 upto poppler-0.68.0. |
33 | 32 | pdftoepdf-poppler0.69.0.cc for poppler-0.69.0. |
34 | 33 | pdftoepdf-poppler0.70.0.cc for poppler-0.70.0 and poppler-0.70.1. |
35 | 34 | pdftoepdf-poppler0.71.0.cc for poppler-0.71.0. |
36 | 35 | pdftoepdf-poppler0.72.0.cc for poppler-0.72.0 upto poppler-0.74.0. |
37 | pdftoepdf-poppler0.75.0.cc for poppler-0.75.0. | |
38 | pdftoepdf-poppler0.76.0.cc for poppler-0.76.0 and newer. | |
36 | pdftoepdf-poppler0.75.0.cc for poppler-0.75.0 and newer. | |
39 | 37 | Note that pdftosrc-*.cc and pdftoepdf-*.cc should be |
40 | 38 | renamed as pdftosrc.cc, and pdftoepdf.cc, respectively, before |
41 | 39 | compilation. |
22 | 22 | by Arch Linux. A little modifications are made to avoid a crash for |
23 | 23 | some kind of pdf images, such as figure_missing.pdf in gnuplot. |
24 | 24 | The poppler should be 0.72.0 or newer versions. |
25 | It is tested upto the poppler 0.74.0. | |
26 | 25 | POPPLER_VERSION should be defined. |
27 | 26 | */ |
28 | 27 |
21 | 21 | https://git.archlinux.org/svntogit/packages.git/plain/texlive-bin/trunk |
22 | 22 | by Arch Linux. A little modifications are made to avoid a crash for |
23 | 23 | some kind of pdf images, such as figure_missing.pdf in gnuplot. |
24 | The poppler should be 0.75.0. | |
24 | The poppler should be 0.75.0 or newer versions. | |
25 | 25 | POPPLER_VERSION should be defined. |
26 | 26 | */ |
27 | 27 |
0 | /* | |
1 | Copyright 1996-2017 Han The Thanh, <thanh@pdftex.org> | |
2 | ||
3 | This file is part of pdfTeX. | |
4 | ||
5 | pdfTeX is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | pdfTeX is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License along | |
16 | with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
19 | /* | |
20 | This is based on the patch texlive-poppler-0.59.patch <2017-09-19> at | |
21 | https://git.archlinux.org/svntogit/packages.git/plain/texlive-bin/trunk | |
22 | by Arch Linux. A little modifications are made to avoid a crash for | |
23 | some kind of pdf images, such as figure_missing.pdf in gnuplot. | |
24 | The poppler should be 0.76.0 or newer versions. | |
25 | POPPLER_VERSION should be defined. | |
26 | */ | |
27 | ||
28 | /* Do this early in order to avoid a conflict between | |
29 | MINGW32 <rpcndr.h> defining 'boolean' as 'unsigned char' and | |
30 | <kpathsea/types.h> defining Pascal's boolean as 'int'. | |
31 | */ | |
32 | #include <w2c/config.h> | |
33 | #include <kpathsea/lib.h> | |
34 | ||
35 | #include <stdlib.h> | |
36 | #include <math.h> | |
37 | #include <stddef.h> | |
38 | #include <stdio.h> | |
39 | #include <string.h> | |
40 | #include <ctype.h> | |
41 | ||
42 | #ifdef POPPLER_VERSION | |
43 | #include <dirent.h> | |
44 | #include <poppler-config.h> | |
45 | #include <goo/GooString.h> | |
46 | #include <goo/gmem.h> | |
47 | #include <goo/gfile.h> | |
48 | #define GString GooString | |
49 | #else | |
50 | #error POPPLER_VERSION should be defined. | |
51 | #endif | |
52 | #include <assert.h> | |
53 | ||
54 | #include "Object.h" | |
55 | #include "Stream.h" | |
56 | #include "Array.h" | |
57 | #include "Dict.h" | |
58 | #include "XRef.h" | |
59 | #include "Catalog.h" | |
60 | #include "Link.h" | |
61 | #include "Page.h" | |
62 | #include "GfxFont.h" | |
63 | #include "PDFDoc.h" | |
64 | #include "GlobalParams.h" | |
65 | #include "Error.h" | |
66 | ||
67 | // This file is mostly C and not very much C++; it's just used to interface | |
68 | // the functions of xpdf, which are written in C++. | |
69 | ||
70 | extern "C" { | |
71 | #include <pdftexdir/ptexmac.h> | |
72 | #include <pdftexdir/pdftex-common.h> | |
73 | ||
74 | // These functions from pdftex.web gets declared in pdftexcoerce.h in the | |
75 | // usual web2c way, but we cannot include that file here because C++ | |
76 | // does not allow it. | |
77 | extern int getpdfsuppresswarningpagegroup(void); | |
78 | extern integer getpdfsuppressptexinfo(void); | |
79 | extern integer zround(double); | |
80 | } | |
81 | ||
82 | // The prefix "PTEX" for the PDF keys is special to pdfTeX; | |
83 | // this has been registered with Adobe by Hans Hagen. | |
84 | ||
85 | #define pdfkeyprefix "PTEX" | |
86 | ||
87 | #define MASK_SUPPRESS_PTEX_FULLBANNER 0x01 | |
88 | #define MASK_SUPPRESS_PTEX_FILENAME 0x02 | |
89 | #define MASK_SUPPRESS_PTEX_PAGENUMBER 0x04 | |
90 | #define MASK_SUPPRESS_PTEX_INFODICT 0x08 | |
91 | ||
92 | // When copying the Resources of the selected page, all objects are copied | |
93 | // recusively top-down. Indirect objects however are not fetched during | |
94 | // copying, but get a new object number from pdfTeX and then will be | |
95 | // appended into a linked list. Duplicates are checked and removed from the | |
96 | // list of indirect objects during appending. | |
97 | ||
98 | enum InObjType { | |
99 | objFont, | |
100 | objFontDesc, | |
101 | objOther | |
102 | }; | |
103 | ||
104 | struct InObj { | |
105 | Ref ref; // ref in original PDF | |
106 | InObjType type; // object type | |
107 | InObj *next; // next entry in list of indirect objects | |
108 | int num; // new object number in output PDF | |
109 | fd_entry *fd; // pointer to /FontDescriptor object structure | |
110 | int enc_objnum; // Encoding for objFont | |
111 | int written; // has it been written to output PDF? | |
112 | }; | |
113 | ||
114 | struct UsedEncoding { | |
115 | int enc_objnum; | |
116 | GfxFont *font; | |
117 | UsedEncoding *next; | |
118 | }; | |
119 | ||
120 | static InObj *inObjList; | |
121 | static UsedEncoding *encodingList; | |
122 | static bool isInit = false; | |
123 | ||
124 | // -------------------------------------------------------------------- | |
125 | // Maintain list of open embedded PDF files | |
126 | // -------------------------------------------------------------------- | |
127 | ||
128 | struct PdfDocument { | |
129 | char *file_name; | |
130 | PDFDoc *doc; | |
131 | XRef *xref; | |
132 | InObj *inObjList; | |
133 | int occurences; // number of references to the document; the doc can be | |
134 | // deleted when this is negative | |
135 | PdfDocument *next; | |
136 | }; | |
137 | ||
138 | static PdfDocument *pdfDocuments = 0; | |
139 | ||
140 | static XRef *xref = 0; | |
141 | ||
142 | // Returns pointer to PdfDocument record for PDF file. | |
143 | // Creates a new record if it doesn't exist yet. | |
144 | // xref is made current for the document. | |
145 | ||
146 | static PdfDocument *find_add_document(char *file_name) | |
147 | { | |
148 | PdfDocument *p = pdfDocuments; | |
149 | while (p && strcmp(p->file_name, file_name) != 0) | |
150 | p = p->next; | |
151 | if (p) { | |
152 | xref = p->xref; | |
153 | (p->occurences)++; | |
154 | return p; | |
155 | } | |
156 | p = new PdfDocument; | |
157 | p->file_name = xstrdup(file_name); | |
158 | p->xref = xref = 0; | |
159 | p->occurences = 0; | |
160 | GString *docName = new GString(p->file_name); | |
161 | p->doc = new PDFDoc(docName); // takes ownership of docName | |
162 | if (!p->doc->isOk() || !p->doc->okToPrint()) { | |
163 | pdftex_fail("xpdf: reading PDF image failed"); | |
164 | } | |
165 | p->inObjList = 0; | |
166 | p->next = pdfDocuments; | |
167 | pdfDocuments = p; | |
168 | return p; | |
169 | } | |
170 | ||
171 | // Deallocate a PdfDocument with all its resources | |
172 | ||
173 | static void delete_document(PdfDocument * pdf_doc) | |
174 | { | |
175 | PdfDocument **p = &pdfDocuments; | |
176 | while (*p && *p != pdf_doc) | |
177 | p = &((*p)->next); | |
178 | // should not happen: | |
179 | if (!*p) | |
180 | return; | |
181 | // unlink from list | |
182 | *p = pdf_doc->next; | |
183 | // free pdf_doc's resources | |
184 | InObj *r, *n; | |
185 | for (r = pdf_doc->inObjList; r != 0; r = n) { | |
186 | n = r->next; | |
187 | delete r; | |
188 | } | |
189 | xref = pdf_doc->xref; | |
190 | delete pdf_doc->doc; | |
191 | xfree(pdf_doc->file_name); | |
192 | delete pdf_doc; | |
193 | } | |
194 | ||
195 | // -------------------------------------------------------------------- | |
196 | ||
197 | static int addEncoding(GfxFont * gfont) | |
198 | { | |
199 | UsedEncoding *n; | |
200 | n = new UsedEncoding; | |
201 | n->next = encodingList; | |
202 | encodingList = n; | |
203 | n->font = gfont; | |
204 | n->enc_objnum = pdfnewobjnum(); | |
205 | return n->enc_objnum; | |
206 | } | |
207 | ||
208 | #define addFont(ref, fd, enc_objnum) \ | |
209 | addInObj(objFont, ref, fd, enc_objnum) | |
210 | ||
211 | // addFontDesc is only used to avoid writing the original FontDescriptor | |
212 | // from the PDF file. | |
213 | ||
214 | #define addFontDesc(ref, fd) \ | |
215 | addInObj(objFontDesc, ref, fd, 0) | |
216 | ||
217 | #define addOther(ref) \ | |
218 | addInObj(objOther, ref, 0, 0) | |
219 | ||
220 | static int addInObj(InObjType type, Ref ref, fd_entry * fd, int e) | |
221 | { | |
222 | InObj *p, *q, *n = new InObj; | |
223 | if (ref.num == 0) | |
224 | pdftex_fail("PDF inclusion: invalid reference"); | |
225 | n->ref = ref; | |
226 | n->type = type; | |
227 | n->next = 0; | |
228 | n->fd = fd; | |
229 | n->enc_objnum = e; | |
230 | n->written = 0; | |
231 | if (inObjList == 0) | |
232 | inObjList = n; | |
233 | else { | |
234 | for (p = inObjList; p != 0; p = p->next) { | |
235 | if (p->ref.num == ref.num && p->ref.gen == ref.gen) { | |
236 | delete n; | |
237 | return p->num; | |
238 | } | |
239 | q = p; | |
240 | } | |
241 | // it is important to add new objects at the end of the list, | |
242 | // because new objects are being added while the list is being | |
243 | // written out. | |
244 | q->next = n; | |
245 | } | |
246 | if (type == objFontDesc) | |
247 | n->num = get_fd_objnum(fd); | |
248 | else | |
249 | n->num = pdfnewobjnum(); | |
250 | return n->num; | |
251 | } | |
252 | ||
253 | #if 0 /* unusewd */ | |
254 | static int getNewObjectNumber(Ref ref) | |
255 | { | |
256 | InObj *p; | |
257 | if (inObjList == 0) { | |
258 | pdftex_fail("No objects copied yet"); | |
259 | } else { | |
260 | for (p = inObjList; p != 0; p = p->next) { | |
261 | if (p->ref.num == ref.num && p->ref.gen == ref.gen) { | |
262 | return p->num; | |
263 | } | |
264 | } | |
265 | pdftex_fail("Object not yet copied: %i %i", ref.num, ref.gen); | |
266 | } | |
267 | #ifdef _MSC_VER | |
268 | /* Never reached, but without __attribute__((noreturn)) for pdftex_fail() | |
269 | MSVC 5.0 requires an int return value. */ | |
270 | return -60000; | |
271 | #endif | |
272 | } | |
273 | #endif | |
274 | ||
275 | static void copyObject(Object *); | |
276 | ||
277 | static void copyName(char *s) | |
278 | { | |
279 | pdf_puts("/"); | |
280 | for (; *s != 0; s++) { | |
281 | if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' || | |
282 | *s == '.' || *s == '-' || *s == '+') | |
283 | pdfout(*s); | |
284 | else | |
285 | pdf_printf("#%.2X", *s & 0xFF); | |
286 | } | |
287 | } | |
288 | ||
289 | static void copyDictEntry(Object * obj, int i) | |
290 | { | |
291 | Object obj1; | |
292 | copyName((char *)obj->dictGetKey(i)); | |
293 | pdf_puts(" "); | |
294 | obj1 = obj->dictGetValNF(i).copy(); | |
295 | copyObject(&obj1); | |
296 | pdf_puts("\n"); | |
297 | } | |
298 | ||
299 | static void copyDict(Object * obj) | |
300 | { | |
301 | int i, l; | |
302 | if (!obj->isDict()) | |
303 | pdftex_fail("PDF inclusion: invalid dict type <%s>", | |
304 | obj->getTypeName()); | |
305 | for (i = 0, l = obj->dictGetLength(); i < l; ++i) | |
306 | copyDictEntry(obj, i); | |
307 | } | |
308 | ||
309 | static void copyFontDict(Object * obj, InObj * r) | |
310 | { | |
311 | int i, l; | |
312 | char *key; | |
313 | if (!obj->isDict()) | |
314 | pdftex_fail("PDF inclusion: invalid dict type <%s>", | |
315 | obj->getTypeName()); | |
316 | pdf_puts("<<\n"); | |
317 | assert(r->type == objFont); // FontDescriptor is in fd_tree | |
318 | for (i = 0, l = obj->dictGetLength(); i < l; ++i) { | |
319 | key = (char *)obj->dictGetKey(i); | |
320 | if (strncmp("FontDescriptor", key, strlen("FontDescriptor")) == 0 | |
321 | || strncmp("BaseFont", key, strlen("BaseFont")) == 0 | |
322 | || strncmp("Encoding", key, strlen("Encoding")) == 0) | |
323 | continue; // skip original values | |
324 | copyDictEntry(obj, i); | |
325 | } | |
326 | // write new FontDescriptor, BaseFont, and Encoding | |
327 | pdf_printf("/FontDescriptor %d 0 R\n", get_fd_objnum(r->fd)); | |
328 | pdf_printf("/BaseFont %d 0 R\n", get_fn_objnum(r->fd)); | |
329 | pdf_printf("/Encoding %d 0 R\n", r->enc_objnum); | |
330 | pdf_puts(">>"); | |
331 | } | |
332 | ||
333 | static void copyStream(Stream * str) | |
334 | { | |
335 | int c, c2 = 0; | |
336 | str->reset(); | |
337 | while ((c = str->getChar()) != EOF) { | |
338 | pdfout(c); | |
339 | c2 = c; | |
340 | } | |
341 | pdflastbyte = c2; | |
342 | } | |
343 | ||
344 | static void copyProcSet(Object * obj) | |
345 | { | |
346 | int i, l; | |
347 | Object procset; | |
348 | if (!obj->isArray()) | |
349 | pdftex_fail("PDF inclusion: invalid ProcSet array type <%s>", | |
350 | obj->getTypeName()); | |
351 | pdf_puts("/ProcSet [ "); | |
352 | for (i = 0, l = obj->arrayGetLength(); i < l; ++i) { | |
353 | procset = obj->arrayGetNF(i).copy(); | |
354 | if (!procset.isName()) | |
355 | pdftex_fail("PDF inclusion: invalid ProcSet entry type <%s>", | |
356 | procset.getTypeName()); | |
357 | copyName((char *)procset.getName()); | |
358 | pdf_puts(" "); | |
359 | } | |
360 | pdf_puts("]\n"); | |
361 | } | |
362 | ||
363 | #define REPLACE_TYPE1C true | |
364 | ||
365 | static bool embeddableFont(Object * fontdesc) | |
366 | { | |
367 | Object fontfile, ffsubtype; | |
368 | ||
369 | if (!fontdesc->isDict()) | |
370 | return false; | |
371 | fontfile = fontdesc->dictLookup("FontFile"); | |
372 | if (fontfile.isStream()) | |
373 | return true; | |
374 | if (REPLACE_TYPE1C) { | |
375 | fontfile = fontdesc->dictLookup("FontFile3"); | |
376 | if (!fontfile.isStream()) | |
377 | return false; | |
378 | ffsubtype = fontfile.streamGetDict()->lookup("Subtype"); | |
379 | return ffsubtype.isName() && !strcmp(ffsubtype.getName(), "Type1C"); | |
380 | } | |
381 | return false; | |
382 | } | |
383 | ||
384 | static void copyFont(char *tag, Object * fontRef) | |
385 | { | |
386 | Object fontdict, subtype, basefont, fontdescRef, fontdesc, charset, | |
387 | stemV; | |
388 | GfxFont *gfont; | |
389 | fd_entry *fd; | |
390 | fm_entry *fontmap; | |
391 | // Check whether the font has already been embedded before analysing it. | |
392 | InObj *p; | |
393 | Ref ref = fontRef->getRef(); | |
394 | for (p = inObjList; p; p = p->next) { | |
395 | if (p->ref.num == ref.num && p->ref.gen == ref.gen) { | |
396 | copyName(tag); | |
397 | pdf_printf(" %d 0 R ", p->num); | |
398 | return; | |
399 | } | |
400 | } | |
401 | // Only handle included Type1 (and Type1C) fonts; anything else will be copied. | |
402 | // Type1C fonts are replaced by Type1 fonts, if REPLACE_TYPE1C is true. | |
403 | fontdict = fontRef->fetch(xref); | |
404 | fontdesc = Object(objNull); | |
405 | if (fontdict.isDict()) { | |
406 | subtype = fontdict.dictLookup("Subtype"); | |
407 | basefont = fontdict.dictLookup("BaseFont"); | |
408 | fontdescRef = fontdict.dictLookupNF("FontDescriptor").copy(); | |
409 | if (fontdescRef.isRef()) { | |
410 | fontdesc = fontdescRef.fetch(xref); | |
411 | } | |
412 | } | |
413 | if (!fixedinclusioncopyfont && fontdict.isDict() | |
414 | && subtype.isName() | |
415 | && !strcmp(subtype.getName(), "Type1") | |
416 | && basefont.isName() | |
417 | && fontdescRef.isRef() | |
418 | && fontdesc.isDict() | |
419 | && embeddableFont(&fontdesc) | |
420 | && (fontmap = lookup_fontmap((char *)basefont.getName())) != NULL) { | |
421 | // round /StemV value, since the PDF input is a float | |
422 | // (see Font Descriptors in PDF reference), but we only store an | |
423 | // integer, since we don't want to change the struct. | |
424 | stemV = fontdesc.dictLookup("StemV"); | |
425 | fd = epdf_create_fontdescriptor(fontmap, zround(stemV.getNum())); | |
426 | charset = fontdesc.dictLookup("CharSet"); | |
427 | if (!charset.isNull() && | |
428 | charset.isString() && is_subsetable(fontmap)) | |
429 | epdf_mark_glyphs(fd, (char *)charset.getString()->c_str()); | |
430 | else | |
431 | embed_whole_font(fd); | |
432 | addFontDesc(fontdescRef.getRef(), fd); | |
433 | copyName(tag); | |
434 | gfont = GfxFont::makeFont(xref, tag, fontRef->getRef(), | |
435 | fontdict.getDict()); | |
436 | pdf_printf(" %d 0 R ", addFont(fontRef->getRef(), fd, | |
437 | addEncoding(gfont))); | |
438 | } else { | |
439 | copyName(tag); | |
440 | pdf_puts(" "); | |
441 | copyObject(fontRef); | |
442 | } | |
443 | } | |
444 | ||
445 | static void copyFontResources(Object * obj) | |
446 | { | |
447 | Object fontRef; | |
448 | int i, l; | |
449 | if (!obj->isDict()) | |
450 | pdftex_fail("PDF inclusion: invalid font resources dict type <%s>", | |
451 | obj->getTypeName()); | |
452 | pdf_puts("/Font << "); | |
453 | for (i = 0, l = obj->dictGetLength(); i < l; ++i) { | |
454 | fontRef = obj->dictGetValNF(i).copy(); | |
455 | if (fontRef.isRef()) | |
456 | copyFont((char *)obj->dictGetKey(i), &fontRef); | |
457 | else if (fontRef.isDict()) { // some programs generate pdf with embedded font object | |
458 | copyName((char *)obj->dictGetKey(i)); | |
459 | pdf_puts(" "); | |
460 | copyObject(&fontRef); | |
461 | } | |
462 | else | |
463 | pdftex_fail("PDF inclusion: invalid font in reference type <%s>", | |
464 | fontRef.getTypeName()); | |
465 | } | |
466 | pdf_puts(">>\n"); | |
467 | } | |
468 | ||
469 | static void copyOtherResources(Object * obj, char *key) | |
470 | { | |
471 | // copies all other resources (write_epdf handles Fonts and ProcSets), | |
472 | ||
473 | // if Subtype is present, it must be a name | |
474 | if (strcmp("Subtype", key) == 0) { | |
475 | if (!obj->isName()) { | |
476 | pdftex_warn("PDF inclusion: Subtype in Resources dict is not a name" | |
477 | " (key '%s', type <%s>); ignored.", | |
478 | key, obj->getTypeName()); | |
479 | return; | |
480 | } | |
481 | } else if (!obj->isDict()) { | |
482 | //FIXME: Write the message only to the log file | |
483 | pdftex_warn("PDF inclusion: invalid other resource which is no dict" | |
484 | " (key '%s', type <%s>); ignored.", | |
485 | key, obj->getTypeName()); | |
486 | return; | |
487 | } | |
488 | copyName(key); | |
489 | pdf_puts(" "); | |
490 | copyObject(obj); | |
491 | } | |
492 | ||
493 | // Function onverts double to string; very small and very large numbers | |
494 | // are NOT converted to scientific notation. | |
495 | // n must be a number or real conforming to the implementation limits | |
496 | // of PDF as specified in appendix C.1 of the PDF Ref. | |
497 | // These are: | |
498 | // maximum value of ints is +2^32 | |
499 | // maximum value of reals is +2^15 | |
500 | // smalles values of reals is 1/(2^16) | |
501 | ||
502 | static char *convertNumToPDF(double n) | |
503 | { | |
504 | static const int precision = 6; | |
505 | static const int fact = (int) 1E6; // must be 10^precision | |
506 | static const double epsilon = 0.5E-6; // 2epsilon must be 10^-precision | |
507 | static char buf[64]; | |
508 | // handle very small values: return 0 | |
509 | if (fabs(n) < epsilon) { | |
510 | buf[0] = '0'; | |
511 | buf[1] = '\0'; | |
512 | } else { | |
513 | char ints[64]; | |
514 | int bindex = 0, sindex = 0; | |
515 | int ival, fval; | |
516 | // handle the sign part if n is negative | |
517 | if (n < 0) { | |
518 | buf[bindex++] = '-'; | |
519 | n = -n; | |
520 | } | |
521 | n += epsilon; // for rounding | |
522 | // handle the integer part, simply with sprintf | |
523 | ival = (int) floor(n); | |
524 | n -= ival; | |
525 | sprintf(ints, "%d", ival); | |
526 | while (ints[sindex] != 0) | |
527 | buf[bindex++] = ints[sindex++]; | |
528 | // handle the fractional part up to 'precision' digits | |
529 | fval = (int) floor(n * fact); | |
530 | if (fval) { | |
531 | // set a dot | |
532 | buf[bindex++] = '.'; | |
533 | sindex = bindex + precision; | |
534 | buf[sindex--] = '\0'; | |
535 | // fill up trailing zeros with the string terminator NULL | |
536 | while (((fval % 10) == 0) && (sindex >= bindex)) { | |
537 | buf[sindex--] = '\0'; | |
538 | fval /= 10; | |
539 | } | |
540 | // fill up the fractional part back to front | |
541 | while (sindex >= bindex) { | |
542 | buf[sindex--] = (fval % 10) + '0'; | |
543 | fval /= 10; | |
544 | } | |
545 | } else | |
546 | buf[bindex++] = 0; | |
547 | } | |
548 | return (char *) buf; | |
549 | } | |
550 | ||
551 | static void copyObject(Object * obj) | |
552 | { | |
553 | Object obj1; | |
554 | int i, l, c; | |
555 | Ref ref; | |
556 | char *p; | |
557 | GString *s; | |
558 | if (obj->isBool()) { | |
559 | pdf_printf("%s", obj->getBool()? "true" : "false"); | |
560 | } else if (obj->isInt()) { | |
561 | pdf_printf("%i", obj->getInt()); | |
562 | } else if (obj->isReal()) { | |
563 | pdf_printf("%s", convertNumToPDF(obj->getReal())); | |
564 | } else if (obj->isNum()) { | |
565 | pdf_printf("%s", convertNumToPDF(obj->getNum())); | |
566 | } else if (obj->isString()) { | |
567 | s = (GooString *)obj->getString(); | |
568 | p = (char *)s->c_str(); | |
569 | l = s->getLength(); | |
570 | if (strlen(p) == (unsigned int) l) { | |
571 | pdf_puts("("); | |
572 | for (; *p != 0; p++) { | |
573 | c = (unsigned char) *p; | |
574 | if (c == '(' || c == ')' || c == '\\') | |
575 | pdf_printf("\\%c", c); | |
576 | else if (c < 0x20 || c > 0x7F) | |
577 | pdf_printf("\\%03o", c); | |
578 | else | |
579 | pdfout(c); | |
580 | } | |
581 | pdf_puts(")"); | |
582 | } else { | |
583 | pdf_puts("<"); | |
584 | for (i = 0; i < l; i++) { | |
585 | c = s->getChar(i) & 0xFF; | |
586 | pdf_printf("%.2x", c); | |
587 | } | |
588 | pdf_puts(">"); | |
589 | } | |
590 | } else if (obj->isName()) { | |
591 | copyName((char *)obj->getName()); | |
592 | } else if (obj->isNull()) { | |
593 | pdf_puts("null"); | |
594 | } else if (obj->isArray()) { | |
595 | pdf_puts("["); | |
596 | for (i = 0, l = obj->arrayGetLength(); i < l; ++i) { | |
597 | obj1 = obj->arrayGetNF(i).copy(); | |
598 | if (!obj1.isName()) | |
599 | pdf_puts(" "); | |
600 | copyObject(&obj1); | |
601 | } | |
602 | pdf_puts("]"); | |
603 | } else if (obj->isDict()) { | |
604 | pdf_puts("<<\n"); | |
605 | copyDict(obj); | |
606 | pdf_puts(">>"); | |
607 | } else if (obj->isStream()) { | |
608 | pdf_puts("<<\n"); | |
609 | copyDict(obj->getStream()->getDictObject()); | |
610 | pdf_puts(">>\n"); | |
611 | pdf_puts("stream\n"); | |
612 | copyStream(obj->getStream()->getUndecodedStream()); | |
613 | pdf_puts("\nendstream"); | |
614 | } else if (obj->isRef()) { | |
615 | ref = obj->getRef(); | |
616 | if (ref.num == 0) { | |
617 | pdftex_fail | |
618 | ("PDF inclusion: reference to invalid object" | |
619 | " (is the included pdf broken?)"); | |
620 | } else | |
621 | pdf_printf("%d 0 R", addOther(ref)); | |
622 | } else { | |
623 | pdftex_fail("PDF inclusion: type <%s> cannot be copied", | |
624 | obj->getTypeName()); | |
625 | } | |
626 | } | |
627 | ||
628 | static void writeRefs() | |
629 | { | |
630 | InObj *r; | |
631 | for (r = inObjList; r != 0; r = r->next) { | |
632 | if (!r->written) { | |
633 | r->written = 1; | |
634 | Object obj1 = xref->fetch(r->ref.num, r->ref.gen); | |
635 | if (r->type == objFont) { | |
636 | assert(!obj1.isStream()); | |
637 | pdfbeginobj(r->num, 2); // \pdfobjcompresslevel = 2 is for this | |
638 | copyFontDict(&obj1, r); | |
639 | pdf_puts("\n"); | |
640 | pdfendobj(); | |
641 | } else if (r->type != objFontDesc) { // /FontDescriptor is written via write_fontdescriptor() | |
642 | if (obj1.isStream()) | |
643 | pdfbeginobj(r->num, 0); | |
644 | else | |
645 | pdfbeginobj(r->num, 2); // \pdfobjcompresslevel = 2 is for this | |
646 | copyObject(&obj1); | |
647 | pdf_puts("\n"); | |
648 | pdfendobj(); | |
649 | } | |
650 | } | |
651 | } | |
652 | } | |
653 | ||
654 | static void writeEncodings() | |
655 | { | |
656 | UsedEncoding *r, *n; | |
657 | char *glyphNames[256], *s; | |
658 | int i; | |
659 | for (r = encodingList; r != 0; r = r->next) { | |
660 | for (i = 0; i < 256; i++) { | |
661 | if (r->font->isCIDFont()) { | |
662 | pdftex_fail | |
663 | ("PDF inclusion: CID fonts are not supported" | |
664 | " (try to disable font replacement to fix this)"); | |
665 | } | |
666 | if ((s = (char *)((Gfx8BitFont *) r->font)->getCharName(i)) != 0) | |
667 | glyphNames[i] = s; | |
668 | else | |
669 | glyphNames[i] = notdef; | |
670 | } | |
671 | epdf_write_enc(glyphNames, r->enc_objnum); | |
672 | } | |
673 | for (r = encodingList; r != 0; r = n) { | |
674 | n = r->next; | |
675 | #ifdef POPPLER_VERSION | |
676 | r->font->decRefCnt(); | |
677 | #else | |
678 | #error POPPLER_VERSION should be defined. | |
679 | #endif | |
680 | delete r; | |
681 | } | |
682 | } | |
683 | ||
684 | // get the pagebox according to the pagebox_spec | |
685 | static const PDFRectangle *get_pagebox(Page * page, int pagebox_spec) | |
686 | { | |
687 | if (pagebox_spec == pdfboxspecmedia) | |
688 | return page->getMediaBox(); | |
689 | else if (pagebox_spec == pdfboxspeccrop) | |
690 | return page->getCropBox(); | |
691 | else if (pagebox_spec == pdfboxspecbleed) | |
692 | return page->getBleedBox(); | |
693 | else if (pagebox_spec == pdfboxspectrim) | |
694 | return page->getTrimBox(); | |
695 | else if (pagebox_spec == pdfboxspecart) | |
696 | return page->getArtBox(); | |
697 | else | |
698 | pdftex_fail("PDF inclusion: unknown value of pagebox spec (%i)", | |
699 | (int) pagebox_spec); | |
700 | return page->getMediaBox(); // to make the compiler happy | |
701 | } | |
702 | ||
703 | ||
704 | // Reads various information about the PDF and sets it up for later inclusion. | |
705 | // This will fail if the PDF version of the PDF is higher than | |
706 | // minor_pdf_version_wanted or page_name is given and can not be found. | |
707 | // It makes no sense to give page_name _and_ page_num. | |
708 | // Returns the page number. | |
709 | ||
710 | int | |
711 | read_pdf_info(char *image_name, char *page_name, int page_num, | |
712 | int pagebox_spec, int minor_pdf_version_wanted, | |
713 | int pdf_inclusion_errorlevel) | |
714 | { | |
715 | PdfDocument *pdf_doc; | |
716 | Page *page; | |
717 | const PDFRectangle *pagebox; | |
718 | #ifdef POPPLER_VERSION | |
719 | int pdf_major_version_found, pdf_minor_version_found; | |
720 | #else | |
721 | #error POPPLER_VERSION should be defined. | |
722 | #endif | |
723 | // initialize | |
724 | if (!isInit) { | |
725 | globalParams = new GlobalParams(); | |
726 | globalParams->setErrQuiet(false); | |
727 | isInit = true; | |
728 | } | |
729 | // open PDF file | |
730 | pdf_doc = find_add_document(image_name); | |
731 | epdf_doc = (void *) pdf_doc; | |
732 | ||
733 | // check PDF version | |
734 | // this works only for PDF 1.x -- but since any versions of PDF newer | |
735 | // than 1.x will not be backwards compatible to PDF 1.x, pdfTeX will | |
736 | // then have to changed drastically anyway. | |
737 | #ifdef POPPLER_VERSION | |
738 | pdf_major_version_found = pdf_doc->doc->getPDFMajorVersion(); | |
739 | pdf_minor_version_found = pdf_doc->doc->getPDFMinorVersion(); | |
740 | if ((pdf_major_version_found > 1) | |
741 | || (pdf_minor_version_found > minor_pdf_version_wanted)) { | |
742 | const char *msg = | |
743 | "PDF inclusion: found PDF version <%d.%d>, but at most version <1.%d> allowed"; | |
744 | if (pdf_inclusion_errorlevel > 0) { | |
745 | pdftex_fail(msg, pdf_major_version_found, pdf_minor_version_found, minor_pdf_version_wanted); | |
746 | } else if (pdf_inclusion_errorlevel < 0) { | |
747 | ; /* do nothing */ | |
748 | } else { /* = 0, give warning */ | |
749 | pdftex_warn(msg, pdf_major_version_found, pdf_minor_version_found, minor_pdf_version_wanted); | |
750 | } | |
751 | } | |
752 | #else | |
753 | #error POPPLER_VERSION should be defined. | |
754 | #endif | |
755 | epdf_num_pages = pdf_doc->doc->getCatalog()->getNumPages(); | |
756 | if (page_name) { | |
757 | // get page by name | |
758 | GString name(page_name); | |
759 | LinkDest *link = pdf_doc->doc->findDest(&name); | |
760 | if (link == 0 || !link->isOk()) | |
761 | pdftex_fail("PDF inclusion: invalid destination <%s>", page_name); | |
762 | Ref ref = link->getPageRef(); | |
763 | page_num = pdf_doc->doc->getCatalog()->findPage(ref); | |
764 | if (page_num == 0) | |
765 | pdftex_fail("PDF inclusion: destination is not a page <%s>", | |
766 | page_name); | |
767 | delete link; | |
768 | } else { | |
769 | // get page by number | |
770 | if (page_num <= 0 || page_num > epdf_num_pages) | |
771 | pdftex_fail("PDF inclusion: required page does not exist <%i>", | |
772 | epdf_num_pages); | |
773 | } | |
774 | // get the required page | |
775 | page = pdf_doc->doc->getCatalog()->getPage(page_num); | |
776 | ||
777 | // get the pagebox (media, crop...) to use. | |
778 | pagebox = get_pagebox(page, pagebox_spec); | |
779 | if (pagebox->x2 > pagebox->x1) { | |
780 | epdf_orig_x = pagebox->x1; | |
781 | epdf_width = pagebox->x2 - pagebox->x1; | |
782 | } else { | |
783 | epdf_orig_x = pagebox->x2; | |
784 | epdf_width = pagebox->x1 - pagebox->x2; | |
785 | } | |
786 | if (pagebox->y2 > pagebox->y1) { | |
787 | epdf_orig_y = pagebox->y1; | |
788 | epdf_height = pagebox->y2 - pagebox->y1; | |
789 | } else { | |
790 | epdf_orig_y = pagebox->y2; | |
791 | epdf_height = pagebox->y1 - pagebox->y2; | |
792 | } | |
793 | ||
794 | // get page rotation | |
795 | epdf_rotate = page->getRotate() % 360; | |
796 | if (epdf_rotate < 0) | |
797 | epdf_rotate += 360; | |
798 | ||
799 | // page group | |
800 | if (page->getGroup() != NULL) | |
801 | epdf_has_page_group = 1; // only flag that page group is present; | |
802 | // the actual object number will be | |
803 | // generated in pdftex.web | |
804 | else | |
805 | epdf_has_page_group = 0; // no page group present | |
806 | ||
807 | pdf_doc->xref = pdf_doc->doc->getXRef(); | |
808 | return page_num; | |
809 | } | |
810 | ||
811 | // writes the current epf_doc. | |
812 | // Here the included PDF is copied, so most errors that can happen during PDF | |
813 | // inclusion will arise here. | |
814 | ||
815 | void write_epdf(void) | |
816 | { | |
817 | Page *page; | |
818 | Ref *pageRef; | |
819 | Dict *pageDict; | |
820 | Object contents, obj1, obj2, pageObj, dictObj; | |
821 | Object groupDict; | |
822 | bool writeSepGroup = false; | |
823 | Object info; | |
824 | char *key; | |
825 | char s[256]; | |
826 | int i, l; | |
827 | int rotate; | |
828 | double scale[6] = { 0, 0, 0, 0, 0, 0 }; | |
829 | bool writematrix = false; | |
830 | int suppress_ptex_info = getpdfsuppressptexinfo(); | |
831 | static const char *pageDictKeys[] = { | |
832 | "LastModified", | |
833 | "Metadata", | |
834 | "PieceInfo", | |
835 | "SeparationInfo", | |
836 | // "Group", | |
837 | // "Resources", | |
838 | NULL | |
839 | }; | |
840 | ||
841 | PdfDocument *pdf_doc = (PdfDocument *) epdf_doc; | |
842 | (pdf_doc->occurences)--; | |
843 | xref = pdf_doc->xref; | |
844 | inObjList = pdf_doc->inObjList; | |
845 | encodingList = 0; | |
846 | page = pdf_doc->doc->getCatalog()->getPage(epdf_selected_page); | |
847 | pageRef = pdf_doc->doc->getCatalog()->getPageRef(epdf_selected_page); | |
848 | pageObj = xref->fetch(pageRef->num, pageRef->gen); | |
849 | pageDict = pageObj.getDict(); | |
850 | rotate = page->getRotate(); | |
851 | const PDFRectangle *pagebox; | |
852 | // write the Page header | |
853 | pdf_puts("/Type /XObject\n"); | |
854 | pdf_puts("/Subtype /Form\n"); | |
855 | pdf_puts("/FormType 1\n"); | |
856 | ||
857 | // write additional information | |
858 | if ((suppress_ptex_info & MASK_SUPPRESS_PTEX_FILENAME) == 0) { | |
859 | pdf_printf("/%s.FileName (%s)\n", pdfkeyprefix, | |
860 | convertStringToPDFString(pdf_doc->file_name, | |
861 | strlen(pdf_doc->file_name))); | |
862 | } | |
863 | if ((suppress_ptex_info & MASK_SUPPRESS_PTEX_PAGENUMBER) == 0) { | |
864 | pdf_printf("/%s.PageNumber %i\n", pdfkeyprefix, (int) epdf_selected_page); | |
865 | } | |
866 | if ((suppress_ptex_info & MASK_SUPPRESS_PTEX_INFODICT) == 0) { | |
867 | info = pdf_doc->doc->getDocInfoNF().copy(); | |
868 | if (info.isRef()) { | |
869 | // the info dict must be indirect (PDF Ref p. 61) | |
870 | pdf_printf("/%s.InfoDict ", pdfkeyprefix); | |
871 | pdf_printf("%d 0 R\n", addOther(info.getRef())); | |
872 | } | |
873 | } | |
874 | // get the pagebox (media, crop...) to use. | |
875 | pagebox = get_pagebox(page, epdf_page_box); | |
876 | ||
877 | // handle page rotation | |
878 | if (rotate != 0) { | |
879 | if (rotate % 90 == 0) { | |
880 | // this handles only the simple case: multiple of 90s but these | |
881 | // are the only values allowed according to the reference | |
882 | // (v1.3, p. 78). | |
883 | // the image is rotated around its center. | |
884 | // the /Rotate key is clockwise while the matrix is | |
885 | // counterclockwise :-% | |
886 | tex_printf(", page is rotated %d degrees", rotate); | |
887 | switch (rotate) { | |
888 | case 90: | |
889 | scale[1] = -1; | |
890 | scale[2] = 1; | |
891 | scale[4] = pagebox->x1 - pagebox->y1; | |
892 | scale[5] = pagebox->y1 + pagebox->x2; | |
893 | writematrix = true; | |
894 | break; | |
895 | case 180: | |
896 | scale[0] = scale[3] = -1; | |
897 | scale[4] = pagebox->x1 + pagebox->x2; | |
898 | scale[5] = pagebox->y1 + pagebox->y2; | |
899 | writematrix = true; | |
900 | break; // width and height are exchanged | |
901 | case 270: | |
902 | scale[1] = 1; | |
903 | scale[2] = -1; | |
904 | scale[4] = pagebox->x1 + pagebox->y2; | |
905 | scale[5] = pagebox->y1 - pagebox->x1; | |
906 | writematrix = true; | |
907 | break; | |
908 | } | |
909 | if (writematrix) { // The matrix is only written if the image is rotated. | |
910 | sprintf(s, "/Matrix [%.8f %.8f %.8f %.8f %.8f %.8f]\n", | |
911 | scale[0], | |
912 | scale[1], scale[2], scale[3], scale[4], scale[5]); | |
913 | pdf_puts(stripzeros(s)); | |
914 | } | |
915 | } | |
916 | } | |
917 | ||
918 | sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n", | |
919 | pagebox->x1, pagebox->y1, pagebox->x2, pagebox->y2); | |
920 | pdf_puts(stripzeros(s)); | |
921 | ||
922 | // Metadata validity check (as a stream it must be indirect) | |
923 | dictObj = pageDict->lookupNF("Metadata").copy(); | |
924 | if (!dictObj.isNull() && !dictObj.isRef()) | |
925 | pdftex_warn("PDF inclusion: /Metadata must be indirect object"); | |
926 | ||
927 | // copy selected items in Page dictionary except Resources & Group | |
928 | for (i = 0; pageDictKeys[i] != NULL; i++) { | |
929 | dictObj = pageDict->lookupNF(pageDictKeys[i]).copy(); | |
930 | if (!dictObj.isNull()) { | |
931 | pdf_newline(); | |
932 | pdf_printf("/%s ", pageDictKeys[i]); | |
933 | copyObject(&dictObj); // preserves indirection | |
934 | } | |
935 | } | |
936 | ||
937 | // handle page group | |
938 | dictObj = pageDict->lookupNF("Group").copy(); | |
939 | if (!dictObj.isNull()) { | |
940 | if (pdfpagegroupval == 0) { | |
941 | // another pdf with page group was included earlier on the | |
942 | // same page; copy the Group entry as is. See manual for | |
943 | // info on why this is a warning. | |
944 | if (getpdfsuppresswarningpagegroup() == 0) { | |
945 | pdftex_warn | |
946 | ("PDF inclusion: multiple pdfs with page group included in a single page"); | |
947 | } | |
948 | pdf_newline(); | |
949 | pdf_puts("/Group "); | |
950 | copyObject(&dictObj); | |
951 | } else { | |
952 | // write Group dict as a separate object, since the Page dict also refers to it | |
953 | dictObj = pageDict->lookup("Group"); | |
954 | if (!dictObj.isDict()) | |
955 | pdftex_fail("PDF inclusion: /Group dict missing"); | |
956 | writeSepGroup = true; | |
957 | /* | |
958 | This part is only a single line | |
959 | groupDict = Object(page->getGroup()); | |
960 | in the original patch. In this case, however, pdftex crashes at | |
961 | "delete pdf_doc->doc" in "delete_document()" for inclusion of some | |
962 | kind of pdf images, for example, figure_missing.pdf in gnuplot. | |
963 | A change | |
964 | groupDict = Object(page->getGroup()).copy(); | |
965 | does not improve the situation. | |
966 | The changes below seem to work fine. | |
967 | */ | |
968 | // begin modification | |
969 | groupDict = pageDict->lookup("Group"); | |
970 | const Dict& dic1 = page->getGroup(); | |
971 | const Dict& dic2 = groupDict.getDict(); | |
972 | // replace dic2 in groupDict with dic1 | |
973 | l = dic2.getLength(); | |
974 | for (i = 0; i < l; i++) { | |
975 | groupDict.dictRemove(dic2.getKey(i)); | |
976 | } | |
977 | l = dic1.getLength(); | |
978 | for (i = 0; i < l; i++) { | |
979 | groupDict.dictAdd((const char *)copyString(dic1.getKey(i)), | |
980 | dic1.getValNF(i).copy()); | |
981 | } | |
982 | // end modification | |
983 | pdf_printf("/Group %ld 0 R\n", (long)pdfpagegroupval); | |
984 | } | |
985 | } | |
986 | ||
987 | // write the Resources dictionary | |
988 | if (page->getResourceDict() == NULL) { | |
989 | // Resources can be missing (files without them have been spotted | |
990 | // in the wild); in which case the /Resouces of the /Page will be used. | |
991 | // "This practice is not recommended". | |
992 | pdftex_warn | |
993 | ("PDF inclusion: /Resources missing. 'This practice is not recommended' (PDF Ref)"); | |
994 | } else { | |
995 | Object *obj1 = page->getResourceDictObject(); | |
996 | if (!obj1->isDict()) | |
997 | pdftex_fail("PDF inclusion: invalid resources dict type <%s>", | |
998 | obj1->getTypeName()); | |
999 | pdf_newline(); | |
1000 | pdf_puts("/Resources <<\n"); | |
1001 | for (i = 0, l = obj1->dictGetLength(); i < l; ++i) { | |
1002 | obj2 = obj1->dictGetVal(i); | |
1003 | key = (char *)obj1->dictGetKey(i); | |
1004 | if (strcmp("Font", key) == 0) | |
1005 | copyFontResources(&obj2); | |
1006 | else if (strcmp("ProcSet", key) == 0) | |
1007 | copyProcSet(&obj2); | |
1008 | else | |
1009 | copyOtherResources(&obj2, (char *)key); | |
1010 | } | |
1011 | pdf_puts(">>\n"); | |
1012 | } | |
1013 | ||
1014 | // write the page contents | |
1015 | contents = page->getContents(); | |
1016 | if (contents.isStream()) { | |
1017 | ||
1018 | // Variant A: get stream and recompress under control | |
1019 | // of \pdfcompresslevel | |
1020 | // | |
1021 | // pdfbeginstream(); | |
1022 | // copyStream(contents->getStream()); | |
1023 | // pdfendstream(); | |
1024 | ||
1025 | // Variant B: copy stream without recompressing | |
1026 | // | |
1027 | obj1 = contents.streamGetDict()->lookup("F"); | |
1028 | if (!obj1.isNull()) { | |
1029 | pdftex_fail("PDF inclusion: Unsupported external stream"); | |
1030 | } | |
1031 | obj1 = contents.streamGetDict()->lookup("Length"); | |
1032 | assert(!obj1.isNull()); | |
1033 | pdf_puts("/Length "); | |
1034 | copyObject(&obj1); | |
1035 | pdf_puts("\n"); | |
1036 | obj1 = contents.streamGetDict()->lookup("Filter"); | |
1037 | if (!obj1.isNull()) { | |
1038 | pdf_puts("/Filter "); | |
1039 | copyObject(&obj1); | |
1040 | pdf_puts("\n"); | |
1041 | obj1 = contents.streamGetDict()->lookup("DecodeParms"); | |
1042 | if (!obj1.isNull()) { | |
1043 | pdf_puts("/DecodeParms "); | |
1044 | copyObject(&obj1); | |
1045 | pdf_puts("\n"); | |
1046 | } | |
1047 | } | |
1048 | pdf_puts(">>\nstream\n"); | |
1049 | copyStream(contents.getStream()->getUndecodedStream()); | |
1050 | pdfendstream(); | |
1051 | } else if (contents.isArray()) { | |
1052 | pdfbeginstream(); | |
1053 | for (i = 0, l = contents.arrayGetLength(); i < l; ++i) { | |
1054 | Object contentsobj = contents.arrayGet(i); | |
1055 | copyStream(contentsobj.getStream()); | |
1056 | if (i < l - 1) | |
1057 | pdf_newline(); // add a newline after each stream except the last | |
1058 | } | |
1059 | pdfendstream(); | |
1060 | } else { // the contents are optional, but we need to include an empty stream | |
1061 | pdfbeginstream(); | |
1062 | pdfendstream(); | |
1063 | } | |
1064 | ||
1065 | // write out all indirect objects | |
1066 | writeRefs(); | |
1067 | ||
1068 | // write out all used encodings (and delete list) | |
1069 | writeEncodings(); | |
1070 | ||
1071 | // write the Group dict if needed | |
1072 | if (writeSepGroup) { | |
1073 | pdfbeginobj(pdfpagegroupval, 2); | |
1074 | copyObject(&groupDict); | |
1075 | pdf_puts("\n"); | |
1076 | pdfendobj(); | |
1077 | pdfpagegroupval = 0; // only the 1st included pdf on a page gets its | |
1078 | // Group included in the Page dict | |
1079 | } | |
1080 | ||
1081 | // save object list, xref | |
1082 | pdf_doc->inObjList = inObjList; | |
1083 | pdf_doc->xref = xref; | |
1084 | } | |
1085 | ||
1086 | // Called when an image has been written and it's resources in image_tab are | |
1087 | // freed and it's not referenced anymore. | |
1088 | ||
1089 | void epdf_delete() | |
1090 | { | |
1091 | PdfDocument *pdf_doc = (PdfDocument *) epdf_doc; | |
1092 | xref = pdf_doc->xref; | |
1093 | if (pdf_doc->occurences < 0) { | |
1094 | delete_document(pdf_doc); | |
1095 | } | |
1096 | } | |
1097 | ||
1098 | // Called when PDF embedding system is finalized. | |
1099 | // Now deallocate all remaining PdfDocuments. | |
1100 | ||
1101 | void epdf_check_mem() | |
1102 | { | |
1103 | if (isInit) { | |
1104 | PdfDocument *p, *n; | |
1105 | for (p = pdfDocuments; p; p = n) { | |
1106 | n = p->next; | |
1107 | delete_document(p); | |
1108 | } | |
1109 | // see above for globalParams | |
1110 | delete globalParams; | |
1111 | } | |
1112 | } |
20 | 20 | This is based on the patch texlive-poppler-0.59.patch <2017-09-19> at |
21 | 21 | https://git.archlinux.org/svntogit/packages.git/plain/texlive-bin/trunk |
22 | 22 | by Arch Linux. The poppler should be 0.72.0 or newer versions. |
23 | It is tested upto the poppler 0.75.0. | |
24 | 23 | POPPLER_VERSION should be defined. |
25 | 24 | */ |
26 | 25 |
0 | /* | |
1 | Copyright 1996-2017 Han The Thanh, <thanh@pdftex.org> | |
2 | ||
3 | This file is part of pdfTeX. | |
4 | ||
5 | pdfTeX is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | pdfTeX is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License along | |
16 | with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
19 | /* | |
20 | This is based on the patch texlive-poppler-0.59.patch <2017-09-19> at | |
21 | https://git.archlinux.org/svntogit/packages.git/plain/texlive-bin/trunk | |
22 | by Arch Linux. The poppler should be 0.76.0 or newer versions. | |
23 | POPPLER_VERSION should be defined. | |
24 | */ | |
25 | ||
26 | #include <w2c/config.h> | |
27 | ||
28 | #include <stdlib.h> | |
29 | #include <stddef.h> | |
30 | #include <stdio.h> | |
31 | #include <string.h> | |
32 | #include <ctype.h> | |
33 | ||
34 | #ifdef POPPLER_VERSION | |
35 | #define GString GooString | |
36 | #define xpdfVersion POPPLER_VERSION | |
37 | #include <dirent.h> | |
38 | #include <goo/GooString.h> | |
39 | #include <goo/gmem.h> | |
40 | #include <goo/gfile.h> | |
41 | #else | |
42 | #error POPPLER_VERSION should be defined. | |
43 | #endif | |
44 | #include <assert.h> | |
45 | ||
46 | #include "Object.h" | |
47 | #include "Stream.h" | |
48 | #include "Lexer.h" | |
49 | #include "Parser.h" | |
50 | #include "Array.h" | |
51 | #include "Dict.h" | |
52 | #include "XRef.h" | |
53 | #include "Catalog.h" | |
54 | #include "Page.h" | |
55 | #include "GfxFont.h" | |
56 | #include "PDFDoc.h" | |
57 | #include "GlobalParams.h" | |
58 | #include "Error.h" | |
59 | ||
60 | static XRef *xref = 0; | |
61 | ||
62 | int main(int argc, char *argv[]) | |
63 | { | |
64 | char *p, buf[1024]; | |
65 | PDFDoc *doc; | |
66 | GString *fileName; | |
67 | Stream *s; | |
68 | Object srcStream, srcName, catalogDict; | |
69 | FILE *outfile; | |
70 | char *outname; | |
71 | int objnum = 0, objgen = 0; | |
72 | bool extract_xref_table = false; | |
73 | int c; | |
74 | fprintf(stderr, "pdftosrc version %s\n", xpdfVersion); | |
75 | if (argc < 2) { | |
76 | fprintf(stderr, | |
77 | "Usage: pdftosrc <PDF-file> [<stream-object-number>]\n"); | |
78 | exit(1); | |
79 | } | |
80 | fileName = new GString(argv[1]); | |
81 | globalParams = new GlobalParams(); | |
82 | doc = new PDFDoc(fileName); | |
83 | if (!doc->isOk()) { | |
84 | fprintf(stderr, "Invalid PDF file\n"); | |
85 | exit(1); | |
86 | } | |
87 | if (argc >= 3) { | |
88 | objnum = atoi(argv[2]); | |
89 | if (argc >= 4) | |
90 | objgen = atoi(argv[3]); | |
91 | } | |
92 | xref = doc->getXRef(); | |
93 | catalogDict = xref->getCatalog(); | |
94 | if (!catalogDict.isDict("Catalog")) { | |
95 | fprintf(stderr, "No Catalog found\n"); | |
96 | exit(1); | |
97 | } | |
98 | srcStream = Object(objNull); | |
99 | if (objnum == 0) { | |
100 | srcStream = catalogDict.dictLookup("SourceObject"); | |
101 | static char const_SourceFile[] = "SourceFile"; | |
102 | if (!srcStream.isStream(const_SourceFile)) { | |
103 | fprintf(stderr, "No SourceObject found\n"); | |
104 | exit(1); | |
105 | } | |
106 | srcName = srcStream.getStream()->getDict()->lookup("SourceName"); | |
107 | if (!srcName.isString()) { | |
108 | fprintf(stderr, "No SourceName found\n"); | |
109 | exit(1); | |
110 | } | |
111 | outname = (char *)srcName.getString()->c_str(); | |
112 | // We cannot free srcName, as objname shares its string. | |
113 | // srcName.free(); | |
114 | } else if (objnum > 0) { | |
115 | srcStream = xref->fetch(objnum, objgen); | |
116 | if (!srcStream.isStream()) { | |
117 | fprintf(stderr, "Not a Stream object\n"); | |
118 | exit(1); | |
119 | } | |
120 | sprintf(buf, "%s", fileName->c_str()); | |
121 | if ((p = strrchr(buf, '.')) == 0) | |
122 | p = strchr(buf, 0); | |
123 | if (objgen == 0) | |
124 | sprintf(p, ".%i", objnum); | |
125 | else | |
126 | sprintf(p, ".%i+%i", objnum, objgen); | |
127 | outname = buf; | |
128 | } else { // objnum < 0 means we are extracting the XRef table | |
129 | extract_xref_table = true; | |
130 | sprintf(buf, "%s", fileName->c_str()); | |
131 | if ((p = strrchr(buf, '.')) == 0) | |
132 | p = strchr(buf, 0); | |
133 | sprintf(p, ".xref"); | |
134 | outname = buf; | |
135 | } | |
136 | if (!(outfile = fopen(outname, "wb"))) { | |
137 | fprintf(stderr, "Cannot open file \"%s\" for writing\n", outname); | |
138 | exit(1); | |
139 | } | |
140 | if (extract_xref_table) { | |
141 | int size = xref->getNumObjects(); | |
142 | int i; | |
143 | for (i = 0; i < size; i++) { | |
144 | if (xref->getEntry(i)->offset == 0xffffffff) | |
145 | break; | |
146 | } | |
147 | size = i; | |
148 | fprintf(outfile, "xref\n"); | |
149 | fprintf(outfile, "0 %i\n", size); | |
150 | for (i = 0; i < size; i++) { | |
151 | XRefEntry *e = xref->getEntry(i); | |
152 | if (e->type != xrefEntryCompressed) | |
153 | fprintf(outfile, "%.10lu %.5i %s\n", | |
154 | (long unsigned) e->offset, e->gen, | |
155 | (e->type == xrefEntryFree ? "f" : "n")); | |
156 | else { // e->offset is the object number of the object stream | |
157 | Stream *str; | |
158 | Lexer *lexer; | |
159 | Parser *parser; | |
160 | Object objStr, obj1, obj2; | |
161 | int nObjects, first, n; | |
162 | int localOffset = 0; | |
163 | unsigned int firstOffset; | |
164 | ||
165 | objStr = xref->fetch(e->offset, 0); | |
166 | assert(objStr.isStream()); | |
167 | obj1 = objStr.streamGetDict()->lookup("N"); | |
168 | nObjects = obj1.getInt(); | |
169 | obj1 = objStr.streamGetDict()->lookup("First"); | |
170 | first = obj1.getInt(); | |
171 | firstOffset = objStr.getStream()->getBaseStream()->getStart() + first; | |
172 | ||
173 | // parse the header: object numbers and offsets | |
174 | objStr.streamReset(); | |
175 | str = new EmbedStream(objStr.getStream(), Object(objNull), true, first); | |
176 | parser = new Parser(xref, str, false); | |
177 | for (n = 0; n < nObjects; ++n) { | |
178 | obj1 = parser->getObj(); | |
179 | obj2 = parser->getObj(); | |
180 | if (n == e->gen) | |
181 | localOffset = obj2.getInt(); | |
182 | } | |
183 | while (str->getChar() != EOF) ; | |
184 | delete parser; | |
185 | ||
186 | fprintf(outfile, "%.10lu 00000 n\n", | |
187 | (long unsigned)(firstOffset + localOffset)); | |
188 | } | |
189 | } | |
190 | } else { | |
191 | s = srcStream.getStream(); | |
192 | s->reset(); | |
193 | while ((c = s->getChar()) != EOF) | |
194 | fputc(c, outfile); | |
195 | } | |
196 | if (objnum == 0) | |
197 | fprintf(stderr, "Source file extracted to %s\n", outname); | |
198 | else if (objnum > 0) | |
199 | fprintf(stderr, "Stream object extracted to %s\n", outname); | |
200 | else | |
201 | fprintf(stderr, "Cross-reference table extracted to %s\n", outname); | |
202 | fclose(outfile); | |
203 | delete doc; | |
204 | delete globalParams; | |
205 | } |
0 | 0 | 2019-05-06 Hironori Kitagawa <h_kitagawa2001@yahoo.co.jp> |
1 | 1 | |
2 | 2 | * ptex-base.ch: |
3 | Make appropreate comparison of U+0100 by \if in upTeX. | |
3 | Make appropriate comparison of U+0100 by \if in upTeX. | |
4 | 4 | https://github.com/texjporg/tex-jp-build/issues/68 |
5 | Re-eval kcatcode of Japanese character token in \if and \ifcat. | |
6 | https://github.com/texjporg/ptex-manual/issues/4 | |
5 | 7 | |
6 | 8 | 2019-02-03 Hironori Kitagawa <h_kitagawa2001@yahoo.co.jp> |
7 | 9 |
58 | 58 | % (2017-09-07) HK pTeX p3.7.2 More restrictions on direction change commands. |
59 | 59 | % (2018-01-21) HK Added \ptexversion primitive and co. pTeX p3.8. |
60 | 60 | % (2018-04-14) HK pTeX p3.8.1 Bug fix for discontinuous KINSOKU table. |
61 | % (2019-02-03) HK pTeX p3.8.2 Change \inhibitglue, add \disinhibitglue. | |
61 | 62 | % |
62 | 63 | |
63 | 64 | @x |
0 | 2019-05-25 TANAKA Takuji <ttk@t-lab.opal.ne.jp> | |
1 | ||
2 | * uptex-m.ch: | |
3 | Correct upTeX_revision ".25", upTeX_version_string "-u1.25". | |
4 | ||
0 | 5 | 2019-05-06 TANAKA Takuji <ttk@t-lab.opal.ne.jp> |
1 | 6 | |
2 | 7 | * uptex-m.ch, upbibtex.ch, updvitype.ch, uppltotf.ch, uptftopl.ch, |
3 | 8 | uptex_version.h: upTeX version u1.25. |
4 | * kanji.c: | |
9 | * kanji.c, kanji.h: | |
5 | 10 | Fix bug of kcatcode at Fullwidth ASCII variants and |
6 | 11 | Halfwidth Katakana variants from Yusuke Terada san: |
7 | 12 | https://github.com/texjporg/tex-jp-build/pull/79 |
0 | % This is a change file for upTeX u1.24 | |
0 | % This is a change file for upTeX u1.25 | |
1 | 1 | % By Takuji Tanaka. |
2 | 2 | % |
3 | 3 | % (02/26/2007) TTK upTeX u0.01 |
47 | 47 | {printed when \pTeX\ starts} |
48 | 48 | @# |
49 | 49 | @d upTeX_version=1 |
50 | @d upTeX_revision==".24" | |
51 | @d upTeX_version_string=='-u1.24' {current u\pTeX\ version} | |
50 | @d upTeX_revision==".25" | |
51 | @d upTeX_version_string=='-u1.25' {current u\pTeX\ version} | |
52 | 52 | @# |
53 | 53 | @d upTeX_banner=='This is upTeX, Version 3.14159265',pTeX_version_string,upTeX_version_string |
54 | 54 | @d upTeX_banner_k==upTeX_banner |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for Web2C Tools 2020/dev. | |
2 | # Generated by GNU Autoconf 2.69 for Web2C Tools 2019. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-k@tug.org>. |
5 | 5 | # |
589 | 589 | # Identity of this package. |
590 | 590 | PACKAGE_NAME='Web2C Tools' |
591 | 591 | PACKAGE_TARNAME='web2c-tools' |
592 | PACKAGE_VERSION='2020/dev' | |
593 | PACKAGE_STRING='Web2C Tools 2020/dev' | |
592 | PACKAGE_VERSION='2019' | |
593 | PACKAGE_STRING='Web2C Tools 2019' | |
594 | 594 | PACKAGE_BUGREPORT='tex-k@tug.org' |
595 | 595 | PACKAGE_URL='' |
596 | 596 | |
1327 | 1327 | # Omit some internal or obsolete options to make the list less imposing. |
1328 | 1328 | # This message is too long to be a string in the A/UX 3.1 sh. |
1329 | 1329 | cat <<_ACEOF |
1330 | \`configure' configures Web2C Tools 2020/dev to adapt to many kinds of systems. | |
1330 | \`configure' configures Web2C Tools 2019 to adapt to many kinds of systems. | |
1331 | 1331 | |
1332 | 1332 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1333 | 1333 | |
1397 | 1397 | |
1398 | 1398 | if test -n "$ac_init_help"; then |
1399 | 1399 | case $ac_init_help in |
1400 | short | recursive ) echo "Configuration of Web2C Tools 2020/dev:";; | |
1400 | short | recursive ) echo "Configuration of Web2C Tools 2019:";; | |
1401 | 1401 | esac |
1402 | 1402 | cat <<\_ACEOF |
1403 | 1403 | |
1520 | 1520 | test -n "$ac_init_help" && exit $ac_status |
1521 | 1521 | if $ac_init_version; then |
1522 | 1522 | cat <<\_ACEOF |
1523 | Web2C Tools configure 2020/dev | |
1523 | Web2C Tools configure 2019 | |
1524 | 1524 | generated by GNU Autoconf 2.69 |
1525 | 1525 | |
1526 | 1526 | Copyright (C) 2012 Free Software Foundation, Inc. |
2359 | 2359 | This file contains any messages produced by compilers while |
2360 | 2360 | running configure, to aid debugging if configure makes a mistake. |
2361 | 2361 | |
2362 | It was created by Web2C Tools $as_me 2020/dev, which was | |
2362 | It was created by Web2C Tools $as_me 2019, which was | |
2363 | 2363 | generated by GNU Autoconf 2.69. Invocation command line was |
2364 | 2364 | |
2365 | 2365 | $ $0 $@ |
8046 | 8046 | |
8047 | 8047 | # Define the identity of the package. |
8048 | 8048 | PACKAGE='web2c-tools' |
8049 | VERSION='2020/dev' | |
8049 | VERSION='2019' | |
8050 | 8050 | |
8051 | 8051 | |
8052 | 8052 | cat >>confdefs.h <<_ACEOF |
14575 | 14575 | # report actual input values of CONFIG_FILES etc. instead of their |
14576 | 14576 | # values after options handling. |
14577 | 14577 | ac_log=" |
14578 | This file was extended by Web2C Tools $as_me 2020/dev, which was | |
14578 | This file was extended by Web2C Tools $as_me 2019, which was | |
14579 | 14579 | generated by GNU Autoconf 2.69. Invocation command line was |
14580 | 14580 | |
14581 | 14581 | CONFIG_FILES = $CONFIG_FILES |
14641 | 14641 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
14642 | 14642 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
14643 | 14643 | ac_cs_version="\\ |
14644 | Web2C Tools config.status 2020/dev | |
14644 | Web2C Tools config.status 2019 | |
14645 | 14645 | configured by $0, generated by GNU Autoconf 2.69, |
14646 | 14646 | with options \\"\$ac_cs_config\\" |
14647 | 14647 |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for TeX Live utils 2020/dev. | |
2 | # Generated by GNU Autoconf 2.69 for TeX Live utils 2019. | |
3 | 3 | # |
4 | 4 | # Report bugs to <tex-k@tug.org>. |
5 | 5 | # |
578 | 578 | # Identity of this package. |
579 | 579 | PACKAGE_NAME='TeX Live utils' |
580 | 580 | PACKAGE_TARNAME='tex-live-utils' |
581 | PACKAGE_VERSION='2020/dev' | |
582 | PACKAGE_STRING='TeX Live utils 2020/dev' | |
581 | PACKAGE_VERSION='2019' | |
582 | PACKAGE_STRING='TeX Live utils 2019' | |
583 | 583 | PACKAGE_BUGREPORT='tex-k@tug.org' |
584 | 584 | PACKAGE_URL='' |
585 | 585 | |
1392 | 1392 | # Omit some internal or obsolete options to make the list less imposing. |
1393 | 1393 | # This message is too long to be a string in the A/UX 3.1 sh. |
1394 | 1394 | cat <<_ACEOF |
1395 | \`configure' configures TeX Live utils 2020/dev to adapt to many kinds of systems. | |
1395 | \`configure' configures TeX Live utils 2019 to adapt to many kinds of systems. | |
1396 | 1396 | |
1397 | 1397 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1398 | 1398 | |
1462 | 1462 | |
1463 | 1463 | if test -n "$ac_init_help"; then |
1464 | 1464 | case $ac_init_help in |
1465 | short | recursive ) echo "Configuration of TeX Live utils 2020/dev:";; | |
1465 | short | recursive ) echo "Configuration of TeX Live utils 2019:";; | |
1466 | 1466 | esac |
1467 | 1467 | cat <<\_ACEOF |
1468 | 1468 | |
1748 | 1748 | test -n "$ac_init_help" && exit $ac_status |
1749 | 1749 | if $ac_init_version; then |
1750 | 1750 | cat <<\_ACEOF |
1751 | TeX Live utils configure 2020/dev | |
1751 | TeX Live utils configure 2019 | |
1752 | 1752 | generated by GNU Autoconf 2.69 |
1753 | 1753 | |
1754 | 1754 | Copyright (C) 2012 Free Software Foundation, Inc. |
1849 | 1849 | This file contains any messages produced by compilers while |
1850 | 1850 | running configure, to aid debugging if configure makes a mistake. |
1851 | 1851 | |
1852 | It was created by TeX Live utils $as_me 2020/dev, which was | |
1852 | It was created by TeX Live utils $as_me 2019, which was | |
1853 | 1853 | generated by GNU Autoconf 2.69. Invocation command line was |
1854 | 1854 | |
1855 | 1855 | $ $0 $@ |
6058 | 6058 | |
6059 | 6059 | # Define the identity of the package. |
6060 | 6060 | PACKAGE='tex-live-utils' |
6061 | VERSION='2020/dev' | |
6061 | VERSION='2019' | |
6062 | 6062 | |
6063 | 6063 | |
6064 | 6064 | cat >>confdefs.h <<_ACEOF |
7023 | 7023 | # report actual input values of CONFIG_FILES etc. instead of their |
7024 | 7024 | # values after options handling. |
7025 | 7025 | ac_log=" |
7026 | This file was extended by TeX Live utils $as_me 2020/dev, which was | |
7026 | This file was extended by TeX Live utils $as_me 2019, which was | |
7027 | 7027 | generated by GNU Autoconf 2.69. Invocation command line was |
7028 | 7028 | |
7029 | 7029 | CONFIG_FILES = $CONFIG_FILES |
7080 | 7080 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
7081 | 7081 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
7082 | 7082 | ac_cs_version="\\ |
7083 | TeX Live utils config.status 2020/dev | |
7083 | TeX Live utils config.status 2019 | |
7084 | 7084 | configured by $0, generated by GNU Autoconf 2.69, |
7085 | 7085 | with options \\"\$ac_cs_config\\" |
7086 | 7086 |