diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/pydocstrip |
Initial commit
Diffstat (limited to 'support/pydocstrip')
-rw-r--r-- | support/pydocstrip/COPYING | 280 | ||||
-rw-r--r-- | support/pydocstrip/FILELIST | 22 | ||||
-rw-r--r-- | support/pydocstrip/README | 39 | ||||
-rw-r--r-- | support/pydocstrip/README_samples | 19 | ||||
-rw-r--r-- | support/pydocstrip/docstrip.py | 629 | ||||
-rw-r--r-- | support/pydocstrip/vnbase.dtx | 1600 | ||||
-rw-r--r-- | support/pydocstrip/vndriver.dtx | 390 | ||||
-rw-r--r-- | support/pydocstrip/vnparam.dtx | 105 | ||||
-rw-r--r-- | support/pydocstrip/vnr.kins | 80 | ||||
-rw-r--r-- | support/pydocstrip/vnr_cm.kins | 19 | ||||
-rw-r--r-- | support/pydocstrip/vnr_ec.kins | 17 | ||||
-rw-r--r-- | support/pydocstrip/vnr_pp.kins | 40 |
12 files changed, 3240 insertions, 0 deletions
diff --git a/support/pydocstrip/COPYING b/support/pydocstrip/COPYING new file mode 100644 index 0000000000..3a39732cc8 --- /dev/null +++ b/support/pydocstrip/COPYING @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
diff --git a/support/pydocstrip/FILELIST b/support/pydocstrip/FILELIST new file mode 100644 index 0000000000..dc35a37a57 --- /dev/null +++ b/support/pydocstrip/FILELIST @@ -0,0 +1,22 @@ +///////////////////////////////// + +You should open one of these files in an Editor +and learn about the KINS file syntax + +vnr.kins Sample KINS file +vnr_pp.kins Default Preamble/Postamble; this file is imported by vnr.kins +vnr_ec.kins KINS file imported by vnr.kins +vnr_cm.kins KINS file imported by vnr.kins + +////////////////////////////////// + +Below the DTX files used for test. +Please see the DTX's documentation in the standard TeX distribution. + +vnbase.dtx | Sample DTX source files. These files are used by vnr.kins. +vnparam.dtx | These files are part of VNR (Vietnamese Fonts for TeX) +vndriver.dtx | and can be found at http://vnr.sarovar.org/menu=download + +////////////////////////////////// + +tempdir TempDir that is used for storing the output of TEST routine diff --git a/support/pydocstrip/README b/support/pydocstrip/README new file mode 100644 index 0000000000..2cf141eb49 --- /dev/null +++ b/support/pydocstrip/README @@ -0,0 +1,39 @@ +Please visit + http://docstrip.sarovar.org/ +for the full description on `docstrip.py`. + +docstrip.py + +* is the Python version of TeX's `docstrip` utility +* but it use KINS files instead of TeX's INS file. + +* some advance functions of `docstrip.py`: + ---------------------------------------- + + a) Support the switches at the command line, for e.g, + docstrip.py -e "test=0;foo=1" + or + docstrip.py -e "test=1;foo=1" + + With this features, + we can easily create a quite sophisticated generation. + + b) Support the source-file-time checking: + + If the (DTX) source file havenot changes, the `docstrip.py` + knows this and skips the generation. So if we have many DTX + files, or the DTX files have quite big size, we may save + very much time of generation. + + (The behavior can be overwritten by using `--force` option.) + + c) Can generate only files whose names match a regular expression: + for example: + docstrip.py [...] -g "foo[0-9]\.tex" + will generate "foo1.tex", "foo2.tex" but "foo100.tex" + + d) Can run in DEBUG mode: + + The DEBUG mode is turned on by the `--debug` option. + No file is generated; but we will know what `docstrip.py` + would do in the real mode. diff --git a/support/pydocstrip/README_samples b/support/pydocstrip/README_samples new file mode 100644 index 0000000000..865ca6fd55 --- /dev/null +++ b/support/pydocstrip/README_samples @@ -0,0 +1,19 @@ +This directory contains the samples for `docstrip.py` +See FILELIST for the details. + +Please try one of following codes. +(Watch for the results saved in ./tempdir before try any other code!) + + docstrip.py -f -j vnr -e "test=0;nopre=1;destdir=./tempdir" + docstrip.py -f -j vnr -e "test=1;nopre=1;destdir=./tempdir" + docstrip.py -f -j vnr -e "test=0;nopre=1;destdir=./tempdir" + docstrip.py -f -j vnr -e "test=0;nopre=0;destdir=./tempdir" + +Because we are running a test, we should use the -f option; +otherwise, the generation occurs only once! + +Under LINUX, you may firstly try + chmod +x docstrip.py + +If you are using Python for WIN32, you may try, for e.g., + "your_python.exe" docstrip.py [...] diff --git a/support/pydocstrip/docstrip.py b/support/pydocstrip/docstrip.py new file mode 100644 index 0000000000..99a985967b --- /dev/null +++ b/support/pydocstrip/docstrip.py @@ -0,0 +1,629 @@ +#!/usr/bin/env python +import string,re,sys,stat,os,getopt,time + +## <VERSION +SELF_VER = 1796 +## VERSION> + +SELF_INFOR = "ktv-docstrip (version Python.%d)" % SELF_VER +GEN_DATE = "%d/%02d/%02d" % time.localtime()[:3] + +## :: Regular Expression + +## file DTX +re_begin = re.compile("%<\*([!a-zA-Z(][()a-zA-Z0-9_|&!]*)>") # begin block +re_end = re.compile("%</([!a-zA-Z(][()a-zA-Z0-9_|&!]*)>") # end block +re_sblock = re.compile("%<([!a-zA-Z(][()a-zA-Z0-9_|&!]*)>(.+\n)")# inline block +re_code = re.compile("^[^%]") # code + +## file KINS +re_from = re.compile("\$from\(([^)]+)\)") +re_gen = re.compile("\$gen\(([^)]+)\)[ ]*\(([^)]+)\)[ ]*(.*)") +re_asg = re.compile("\$([a-z][a-z0-9_]*)[ ]*=[ ]*(.*)") +## re_asg = re.compile("\$([a-z][a-z0-9_]*)[ ]*=[ ]*(.*)") +re_kasg = re.compile("([a-z][a-zA-Z0-9_]*)[ ]*=[ ]*(.*)") +re_com = re.compile("#.*") ## comment line +re_isnum = re.compile("[+|-]*[0-9]+") +re_local = re.compile("\$local\(([^)]+)\)") +re_eof = re.compile("\$eof=([01])") +## re_eoj = re.compile("\$eoj=([01])") +re_import = re.compile("\$import\(([^)]+)\)") ## add, Ky Anh, 2003/12/25 +re_if = re.compile("\$if\(([^)]+)\)") +re_elif = re.compile("\$elif\(([^)]+)\)") +re_exec = re.compile("\$<<<(.*)") +## re_expand = re.compile("\$\([a-z][a-z0-9_]*\)") + +def _xsplit(st): + """Tao list cac terminal/guard, bo qua &,|,!,(,) + Chi tra ve cac list chua co trong danh sach __guards ma thoi + """ + ## last modify: Ky Anh, 2003/12/27 + ## : use global __guards + global __guards + for ops in ['&', '(', ')', '!', '|', ',', ' ']: + st = string.replace(st, ops, ':') + tmp = [] + for ops in string.split(st, ':'): + if (ops != '') and (not ops in __guards): + tmp.append(ops) + __guards.extend(tmp) + __use(tmp,0) + +def _translate(st): # + """Dich mot bieu thuc logic thanh loi chuan cua PYTHON""" + st = "(%s)" % st + idx = 0 + tmpst = "" + find_next_op = 0 + group_level = 0 + while idx < len(st): + if st[idx] == '!': + tmpst = tmpst + "(not " + find_next_op = 1 + elif st[idx] == '(': + tmpst = tmpst + '(' + group_level = group_level + 1 + elif st[idx] == ')': + tmpst = tmpst + ')' + group_level = group_level - 1 + else: # ! + if find_next_op: + while (find_next_op > 0) and (idx < len(st)): + if (st[idx] in __block_ops) or (group_level == 0): + tmpst = tmpst + ')' + st[idx] + find_next_op = 0 + else: + tmpst = tmpst + st[idx] + idx = idx + 1 + else: + tmpst = tmpst + st[idx] + idx = idx +1 + + idx = string.count(tmpst,'(') - string.count(tmpst,')') + while idx > 0 : + tmpst = tmpst + ')' + idx = idx - 1 + return tmpst[1:-1] + +def __setval(guard, value=1): + ## add, Ky Anh, 2003/12/27 + exec("global %s\n%s=%d" % (guard,guard,value)) + +def __use(options, value=1): + ## add, Ky Anh, 2003/12/27 + ## mod, Ky Anh, 2003/12/30, v1792, remove __alpha/__beta option check + for weapon in options: + tmpst = string.strip(weapon) + if tmpst: __setval(tmpst,value) +## if tmpst in __alpha_options: +## __setval(tmpst,1) +## elif tmpst in __beta_options: +## __setval(tmpst,0) +## else: + +def _use(opts_string, value=1): + __use(string.split(opts_string, ","), value) + +def _do_global(): + ## add, Ky Anh, 2003/12/27 +## _force_ +## _gonly_ +## _kins_nopre +## _kins_nopost +## _kins_debug +## _kins_destdir +## jobnames ## list of job (<kins> files) +## __guards ## list of guard in DTX files +## add, Ky Anh, 2003/12/27 +## NO ## list of NO-equivalent (0, No, NO, etc.) +## __block_ops ## list of operators in a DTX guard (block) +## __kins_vars ## list of global kins variables +## __global_kins_vars ## kins variables that are also the global +## variables in this program +## __no_skip_vars ## variables appear in the third part of |$gen| +## command; these variables arenot the <test> +## __alpha_options ## this DTX options will always be set to 1 +## __beta_options ## - 0 +## _tex_ ## output as the INS file + global\ + _force_,\ + _gonly_,\ + _kins_nopre,\ + _kins_nopost,\ + _kins_debug,\ + _kins_destdir,\ + jobnames,\ + __guards,\ + NO,\ + __block_ops,\ + __kins_vars,\ + __global_kins_vars,\ + __no_skip_vars,\ + _tex_,\ + _kins_pre_def,\ + _kins_pos_def +## __alpha_options,\ +## __beta_options + + NO = ['0','no'] + + __block_ops = ['&','|'] ## donot accept the !. See the _translate() + __global_kins_vars = ["pre", "post"] + __no_skip_vars = ["append", "nopost", "nopre",\ + "destdir", "source", "debug"] +## __alpha_options = ["alpha", "com"] +## __beta_options = [] + + jobnames = [] + __guards = [] + + _force_ = 0 + _gonly_ = 0 + _tex_ = 0 + + ## initialize the global variables + ## these variable can be exported, i.e., + ## we can use `--exec cmd' at command line. + _kins_nopre = '0' + _kins_nopost = '0' + _kins_debug = '0' + _kins_destdir = '.' + __kins_vars = ["nopre", "nopost", "destdir", "debug"] + _kins_pre_def = "%% This file was generate\n\ +%% \tfrom the file `$source'\n\ +%% \twith option `$option'\n\ +%% GenDate: $date\n\ +%% Generator: $generator\n" + _kins_pos_def = "%% End of file `$dest'" + + ## init the <special> guards + ## we neednot do this, because if a guard appears in a DTX file + ## it is recognize by _xsplit and then set the value by __use + ## see the defintionof _xplist for more details + ## __use(__alpha_options + __beta_options) + +def _xstrip(options, debug=0): + """Tach ma tu file DTX voi options""" + global __ilines, __output + _use(options, 1) + __output = [] + __level = 0 + __prints = [1] + if debug: print "%s" % ("=" * 72), + for weapon in __ilines: + print_code = 0 + if re_begin.match(weapon): + __level = __level + 1 + if __prints[__level - 1]: # previous block + current_bblock = re_begin.match(weapon).group(1) + exec("print_code=%s" % _translate(current_bblock)) + __prints.append(int(print_code)) + if debug: print "\nlevel%2d %s *%s -> "\ + % (__level,__prints,re_begin.match(weapon).group(1)), + elif re_end.match(weapon): + __level = __level - 1 + if __level < 0: break + __prints.pop() + if debug: print "\nlevel%2d %s /%s -> "\ + % (__level,__prints,re_end.match(weapon).group(1)), + elif re_sblock.match(weapon): # + if __prints[__level]: + current_bblock = re_sblock.match(weapon).group(1) + exec("print_code=%s" % _translate(current_bblock)) + if debug: print "\nlevel%2d %s %s -> "\ + % (__level,__prints,re_sblock.match(weapon).group(1)), + if print_code: + if debug: sys.stdout.write('s') + else: __output.append(re_sblock.match(weapon).group(2)) + if debug: + print "\nlevel%2d %s -> " % (__level,__prints), + elif re_code.match(weapon): + if __prints[__level]: + if debug: sys.stdout.write('n') + else: __output.append(weapon) + if __level: + print \ +"\nThe blocks of your DTX file donot balance.\n\ +To debug, use <docstrip> with `--debug' option." + if debug: print "\n%s" % ("=" * 72) + + _use(options, 0) # reset options' value to 0 + +def _readkins(filename): + ## add, Ky Anh, 2003/12/25 + """Read a KINS file, remove the comment line, and strip the lines. + This function returns a LIST of KINS lines.""" + mykinslines = [] + f = open(filename, 'r') + iline = f.readline() + while iline: + iline = re_com.split(iline)[0] + iline = string.strip(iline) + if re_eof.match(iline): + if re_eof.match(iline).group(1) == '1': + break ## reach END OF FILE + elif iline: + mykinslines.append(iline) + iline = f.readline() + f.close() + return mykinslines + +def _dokins(filename): + """Excute the KINS code. The original name is |_readkins|; this version + wasnot support |$import|. To do |$import|, a new function |_readkins| was + added, and this function is now named |_dokins|.""" + global _kins_pre, _kins_post, kins_lines, _kins_pre_def, _kins_pos_def + kins_lines = [] + __imported = [] # list of imported files + + _kins_pre = _kins_pre_def # default preamble/ + _kins_post = _kins_pos_def # default /postamble + _kins_source= '' + + in_pre = in_post = 0 + in_if = [1] + __iflevel = 0 + __ifcont = [] + + kins_lines = _readkins(filename) + + while kins_lines: + iline = kins_lines.pop(0) +## :: = $if + if re_if.match(iline): + if_value = 0 + __iflevel = __iflevel + 1 + if in_if[__iflevel - 1]: + var_name = re_if.match(iline).group(1) + if re_kasg.match(var_name): + var_value = re_kasg.match(var_name).group(2) + var_name = re_kasg.match(var_name).group(1) + try: + if var_name in __kins_vars: + exec("tmp_value=_kins_%s" % var_name) + else: + exec("tmp_value=_gen_%s" % var_name) + if var_value == tmp_value: + if_value = 1 + except NameError: pass + in_if.append(if_value) +## :: = $elif + elif re_elif.match(iline): + __iflevel = __iflevel - 1 + iline = "$if%s" % iline[5:] + kins_lines.insert(0, iline) +## :: = $else + elif iline == "$else": + in_if[__iflevel] = 1 - in_if[__iflevel] +## :: = $enif + elif iline == "$enif": + __iflevel = __iflevel - 1 + if __iflevel < 0: + sys.stderr.write(\ + "\nerror: to much $enif. The program is going to stop.\n") + sys.exit(1) + else: + in_if.pop() + if __iflevel == 0: + kins_lines[0:0], __ifcont = __ifcont, [] + elif __iflevel: + if in_if[__iflevel]: + __ifcont.append(iline) +## :: = pre, post + elif iline == "$pre": _kins_pre, in_pre = "", 1 + elif iline == "$post": _kins_post, in_post = "", 1 + elif iline == "$enpre": in_pre = 0 + elif iline == "$enpost": in_post = 0 +## ## :: = $(.+) +## elif re_expand.match(iline): +## var_name = re_expand.match(iline).group(1) +## :: = $<<<< + elif re_exec.match(iline): + try: + exec(re_exec.match(iline).group(1)) + except: + sys.stderr.write("E") +## :: = if in_pre, in_post + ## hai do`ng sau pha?i dde^? sau bo^'n do`ng tre^n + elif in_pre: _kins_pre = _kins_pre + iline + '\n' + elif in_post: _kins_post = _kins_post + iline + '\n' +## :: = $from + elif re_from.match(iline): # from macro + _kins_source = re_from.search(iline).group(1) + _readsource(_kins_source) + sys.stderr.write('_') +## :: = $import + elif re_import.match(iline): + _i_file = re_import.match(iline).group(1) + if not _i_file in __imported: + __imported.append(_i_file) + if not string.lower(_i_file[-5:]) == ".kins": + _i_file = _i_file + ".kins" + kins_lines[0:0] = _readkins(_i_file) + sys.stderr.write('=') + else: + sys.stderr.write('*') +## :: = assign + elif re_asg.match(iline): + var_name = re_asg.match(iline).group(1) + var_value= re_asg.match(iline).group(2) +## :: = = $docstrip + if var_name == 'docstrip': # + if SELF_VER < int(var_value): + sys.stderr.write(\ +"need docstrip %d or higher. Current docstrip's version: %d.\n"\ + % (int(var_value), SELF_VER)) + return +## :: = = global kins variables + elif var_name in __global_kins_vars: + exec('global _kins_%s\n_kins_%s="""%s"""'\ + % (var_name, var_name, var_value)) +## :: = = other kins variables + else: + if not var_name in __kins_vars: + __kins_vars.append(var_name) + exec('_kins_%s="""%s"""' % (var_name,var_value)) + if var_name == 'source': _readsource(_kins_source) +## :: = $local + elif re_local.match(iline): + zzz = re_local.match(iline).group(1) + if re_kasg.match(zzz): + var_name = re_kasg.match(zzz).group(1) + var_value = re_kasg.match(zzz).group(2) + exec('_gen_%s="""%s"""' % (var_name,var_value)) +## :: = $gen + elif re_gen.match(iline): # gen macro + gen_des = re_gen.match(iline).group(1) + if (not _gonly_) or (only_files.search(gen_des)): + gen_opt = re_gen.match(iline).group(2) + ## neu $gen co them tham so thu ba + ## tham so nay phai de trong ngoac: (.+) + kins_skip = 0 + _gen_append = '0' # <initial value must be '0'> + _gen_nopre = _kins_nopre # get the global value + _gen_nopost = _kins_nopost # as the initialization + _gen_destdir = _kins_destdir# add 2003/12/10 + _gen_debug = _kins_debug # + if re_gen.search(iline).group(3) != "": + gen_optlist = string.split(\ + re_gen.search(iline).group(3)[1:-1],',') + for item in gen_optlist: + item = string.strip(item) + if item == "append": _gen_append = '1' + elif item == "nopost": _gen_nopost = '1' + elif item == "nopre" : _gen_nopre = '1' + else: + zzz = re_kasg.match(item) + if zzz: + var_name = zzz.group(1) + var_value= str(zzz.group(2)) + if var_name in __no_skip_vars: + exec('_gen_%s="""%s"""' % (var_name,var_value)) + else: + try: + if var_name in __kins_vars: + exec("tmp_value=_kins_%s" % var_name) + else: + exec("tmp_value=_gen_%s" % var_name) + if not var_value == tmp_value: + kins_skip = 1 + break # break the FOR loop + ## donot mention other check + except NameError: + exec('_gen_%s="""%s"""' % (var_name,var_value)) + if kins_skip: + sys.stderr.write('o') + else: + gen_des = "%s/%s" % (_gen_destdir, gen_des) + _gen(gen_des,gen_opt,\ + _gen_append,\ + _gen_nopre,_gen_nopost,\ + _kins_source, _gen_debug) + else: + sys.stderr.write('o') +## :: = anything else + else: pass + if __iflevel != 0: + sys.stderr.write("\nerror: missing $if or $enif\n") + +def _readsource(source): + ## last modify: Ky Anh, 2003/12/27 + ## : according to changes of _xsplit + global __ilines,\ + src_time + __ilines = [] + src_time = os.stat(source)[stat.ST_MTIME] + f = open(source, 'r') + iline = f.readline() # + while iline: + if re_code.match(iline): # code + __ilines.append(iline) + elif re_begin.match(iline): # begin block + __ilines.append(iline) + _xsplit(re_begin.match(iline).group(1)) + elif re_sblock.match(iline):# single block + __ilines.append(iline) + _xsplit(re_sblock.match(iline).group(1)) + elif re_end.match(iline): # end block + __ilines.append(iline) + iline = f.readline() + f.close() + +def _gen(filename, opt,\ + _gen_append='0',\ + _gen_nopre='0', _gen_nopost='0',\ + source_name='', _gen_debug='0'): + + if not _gen_debug in NO: #yes, debug is ON + sys.stderr.write('-') + print "f(%s)s(%s)o(%s)a(%s)npre(%s)npos(%s)bug(%s)"\ + % (filename, source_name, opt,\ + _gen_append, _gen_nopre, _gen_nopost, _gen_debug) + _xstrip(opt, 1) + else: + des = string.split(filename, '/')[-1:][0] + try: + dest_time = os.stat(filename)[stat.ST_MTIME] + except os.error: + dest_time = 0 + + if _force_ or (src_time > dest_time): + try: + if _gen_append in NO: + g = open(filename, 'w') + sys.stderr.write('.') + else: + g = open(filename, 'a') + g.write('\n') + sys.stderr.write('+') + except IOError: + sys.stderr.write('X') + return + + if _gen_nopre in NO: + global _kins_pre + ## expand |preample| + tmp__pre = string.replace(_kins_pre,"$date", GEN_DATE) + tmp__pre = string.replace(tmp__pre, "$c", '#') + tmp__pre = string.replace(tmp__pre, "$generator", SELF_INFOR) + tmp__pre = string.replace(tmp__pre, "$option", opt) + tmp__pre = string.replace(tmp__pre, "$dest", des) + tmp__pre = string.replace(tmp__pre, "$source", source_name) + g.write(tmp__pre) +## if _tex_: +## if tmp__pre[-1:] == '\n': +## tmp__pre = tmp__pre[:-1] +## print "\def\ktvpre{^^A" +## print string.replace(tmp__pre, "\n", "^^J^^A\n"), +## print "}\usepreamble\ktvpre" + _xstrip(opt, 0) + g.writelines(__output) + if _tex_: + print "\\generate{\\file{%s}{\\from{%s}{%s}}}"\ + % (filename, source_name, opt) + + if _gen_nopost in NO: + global _kins_post + tmp__pre = _kins_post + ## expand |posamble|. Only macro "$dest" is allowed. + tmp__pre = string.replace(_kins_post,"$dest", des) + tmp__pre = string.replace(tmp__pre, "$c", "#") + g.write(tmp__pre)# the tail + + g.close() + os.utime(filename, (src_time, src_time)) + else: + sys.stderr.write('|') + +def usage(): + sys.stdout.write(\ +"""Usage: docstrip [options] file1 file2... + -e --exec code excute <code> before any job + (only the assignments are accepted) + -g --gen expr generate only files whose names + match the regular expression <expr> + -j --job job specify the kins file named <job> + (the extension `.kins' can be omitted) + -t --tex print the (TeX) INS code + -d --debug print debug information (donot generate any file) + -f --force force generatation (skip time check) + -h --help show this message + -v --version print version information and exit +Report: + . generate sucessfully + + generate in `append' mode + o skip file (specified by <kins> file) + ? some things wrong occur + _ opening new source file + = importing a kins file + * file is already imported. Inogre it! + X cannot open file for writting + E failed on excuting embeded python code + | skip file (the source time <= the destination time) +Within the `--debug' option: + - debugging + n normal code + s single block code +""") + +if __name__ == '__main__': + try: + opts, args\ + = getopt.getopt(sys.argv[1:],\ + "vdhftg:e:j:",\ + ["debug","tex","job=","version", "gen=","force","help","exec="]) + except: + sys.stderr.write("Please try |docstrip.py --help|\n") + sys.exit(1) + + _do_global() + + for o, a in opts: + if o in ("-h", "--help"): + usage() + sys.exit(0) + elif o in ("-v", "--version"): + sys.stdout.write("%s\n" % SELF_INFOR) + sys.exit(0) + elif o in ("-f", "--force"): + _force_ = 1 + elif o in ("-t", "--tex"): + _tex_ = 1 + elif o in ("-d", "--debug"): + _kins_debug = '1' + elif o in ("-g", "--gen"): + _gonly_ = 1 + only_files = re.compile(a) + sys.stderr.write(" genonly = %s\n" % a) + elif o in ("-j", "--job"): + if not string.lower(a[-5:]) == ".kins": + a = a + ".kins" + jobnames.append(a) + elif o in ("-e", "--exec"): + a = string.split(a, ';') + for code in a: + zzz = re_kasg.match(string.strip(code)) + if zzz: + var_name = zzz.group(1) + var_value= zzz.group(2) + exec('_kins_%s="""%s"""' % (var_name,var_value)) + if not var_name in __kins_vars: + __kins_vars.append(var_name) + sys.stderr.write(" %s = %s\n" % (var_name,var_value)) + else: + sys.stderr.write(" ?code: %s\n" % code) + + for item in args: + if not string.lower(item[-5:]) == ".kins": + item = item + ".kins" + jobnames.append(item) + + if jobnames == []: + sys.stderr.write("Please try |docstrip.py --help|\n") + sys.exit(1) + + if _tex_: + print\ +"%%%% This file was generated by `%s'\n\ +%%%% from the source(s) %s\n\ +\\input docstrip.tex" % (SELF_INFOR, jobnames) + + for jobname in jobnames: + if os.path.isfile(jobname): + sys.stderr.write("\n<<%s>>\n" % jobname) + _dokins(jobname) + else: + sys.stderr.write("\n<<%s>>: cannot open this file\n" % jobname) + if _tex_: + print "\\endbatchfile\n\\endinput\n%% End of file." + + sys.stderr.write("(ok)\n") + +#################### +## END OF PROGRAM ## +#################### + +## TO DO: + +## 2003/12/27: +## $if, $fi, $else, $elif diff --git a/support/pydocstrip/vnbase.dtx b/support/pydocstrip/vnbase.dtx new file mode 100644 index 0000000000..080ade8f52 --- /dev/null +++ b/support/pydocstrip/vnbase.dtx @@ -0,0 +1,1600 @@ +% \iffalse
+%<dtx>\ProvidesFile{vnbase.dtx}[2003/11/01 v01.01 VNR.KTV.DTX.Base]
+% \fi
+%
+% \section{Basic macros}
+%
+% \begin{macrocode}
+%<*vnbase>
+% \end{macrocode}
+%
+% §Þnh nghÜa tÊt c¶ c¸c macro ®îc dïng bëi |VNR|.
+%
+% \subsection{Generic Macros}
+%
+% \danger
+% V× |mfplain.mp| kh«ng ®îc cËp nhËt cïng víi |plain.mf|,
+% nªn ®Ó |MetaPost| cã thÓ lµm viÖc víi |ec| fonts,
+% ta ph¶i cÇn c¸c dßng sau (chÐp tõ |plain.mf|).
+% \endanger
+%
+% \begin{macrocode}
+%<*test>
+vardef whatever = save ?; ? enddef;
+def killtext text t = enddef;
+%</test>
+% \end{macrocode}
+%
+% \begin{macrocode}
+if unknown exbase:
+ input exbase;
+fi;
+% \end{macrocode}
+%
+% \begin{macrocode}
+if unknown displaying:
+ displaying := 0;
+fi
+% \end{macrocode}
+% Trong *exbase.mf*, macro *ecchar* ®îc ®Þnh nghÜa bëi *|let ecchar=\;|*.
+% \begin{macrocode}
+let vnchar = ecchar;
+let cmchar = ecchar;
+% \end{macrocode}
+%
+% Load |T5| |encoding| vµ c¸c macro ®Þnh nghÜa c¸c hä ch÷ c¸i, hä dÊu.
+% \begin{macrocode}
+input vncode;
+% \end{macrocode}
+%
+% \subsection{Test: Parameters}
+%
+% Parameter for |t5supp-encoding|.
+% \begin{macrocode}
+%<*t5supp>
+% get_acc_pos := 1;
+% gen_t5_supp := 1;
+% if known get_acc_pos or known gen_t5_supp:
+ mag := 100.375;
+% fi
+%</t5supp>
+% \end{macrocode}
+%
+% *(KTV,2003/11/02):*
+% ViÖc ®Æt *|defaultfont:="Times-Roman"|* sÏ sinh ra lçi
+% (kh«ng t×m thÊy font |tfm|) t¬ng øng.
+% Xem thªm trong \href{../doc/vnr_bug_fix.dvi}{vnr_bug_fix}.
+%
+% *(KTV,2003/11/13):*
+% Ph¶i dïng *|prologues:=1|* míi cã thÓ |merge| c¸c output t¹o bëi
+% |MetaPost| b»ng |mpmergeps.py|.
+% (Cha kiÓm tra ®iÒu nµy víi |mergemps.py|.)
+% \begin{macrocode}
+%<*test>
+% show_labels := 1; % value passed in the `makefile'
+% makeXbox := 0; % value passed in the `makefile'
+defaultscale := 1;
+prologues := 1;
+%defaultfont := "Times-Roman";
+if known black_proof:
+ proofcolor := .9999[white, black];
+else:
+ proofcolor := .3[white, black];
+fi
+if known gensize:
+ mag := 20/gensize;
+else: mag := 2; fi
+if known no_labels:
+ def penlabels(text _list) = enddef;
+fi
+%</test>
+% \end{macrocode}
+%
+% \subsection{Test: Letters}
+%
+% Danh s¸ch c¸c ch÷ c¸i ®îc vÏ khi trong \tstmode.
+% Muèn |test| ch÷ c¸i nµo th× chØ viÖc bá dÊu |%| ë tríc ch÷ ®ã.
+% Cã thÓ thùc hiÖn c¸c phÐp g¸n, vÝ dô: *|test_grave:=1|*.
+% \emph{Lu ý:} nh÷ng ch÷ c¸i ®îc test sÏ gåm c¶ ch÷ hoa lÉn ch÷ thêng.
+% (Xem ®Þnh nghÜa cña *grave_fam*, *acute_fam*,... ë \lref{def:accent_fam},
+% ®Þnh nghÜa cña *a_fam*, *d_fam*,... ë \lref{def:letter_fam}.)
+%
+% \begin{multicols}3
+% \begin{macrocode}
+%<*test>
+def testchars =
+%<=def:testchars>
+if known test_grave:
+ grave_fam(,)
+fi if known test_acute:
+ acute_fam(,)
+fi if known test_tilde:
+ tilde_fam(,)
+fi if known test_hook:
+ hook_fam(,)
+fi if known test_dot:
+ dot_fam(,)
+fi if known test_a:
+ a_fam(,)
+fi if known test_e:
+ e_fam(,)
+fi if known test_i:
+ i_fam(,)
+fi if known test_o:
+ o_fam(,)
+fi if known test_u:
+ u_fam(,)
+fi if known test_uhorn:
+ uhorn_fam(,)
+fi if known test_y:
+ y_fam(,)
+fi if known test_d:
+ d_fam(,)
+fi if known test_all_chars:
+ full_fam(,)
+fi
+% a.acute_,
+% a.dot_,
+% a.grave_,
+% a.hook_,
+% a.tilde_,
+% a.breve_,
+% a.breve_.acute_,
+% a.breve_.dot_,
+% a.breve_.grave_,
+% a.breve_.hook_,
+% a.breve_.tilde_,
+% a.circumflex_,
+% a.circumflex_.acute_,
+% a.circumflex_.dot_,
+% a.circumflex_.grave_,
+% a.circumflex_.hook_,
+% a.circumflex_.tilde_,
+% d.bar_,
+% e.acute_,
+% e.dot_,
+% e.grave_,
+% e.hook_,
+% e.tilde_,
+% e.circumflex_,
+% e.circumflex_.acute_,
+% e.circumflex_.dot_,
+% e.circumflex_.grave_,
+% e.circumflex_.hook_,
+% e.circumflex_.tilde_,
+% i.acute_,
+% i.dot_,
+% i.grave_,
+% i.hook_,
+% i.tilde_,
+% o.acute_,
+% o.dot_,
+% o.grave_,
+% o.hook_,
+% o.tilde_,
+% o.circumflex_,
+% o.circumflex_.acute_,
+% o.circumflex_.dot_,
+% o.circumflex_.grave_,
+% o.circumflex_.hook_,
+% o.circumflex_.tilde_,
+% o.horn_,
+% o.horn_.acute_,
+% o.horn_.dot_,
+% o.horn_.grave_,
+% o.horn_.hook_,
+% o.horn_.tilde_,
+% u.acute_,
+% u.dot_,
+% u.grave_,
+% u.hook_,
+% u.tilde_,
+% u.horn_,
+% u.horn_.acute_,
+% u.horn_.dot_,
+% u.horn_.grave_,
+% u.horn_.hook_,
+% u.horn_.tilde_,
+% y.acute_,
+% y.dot_,
+% y.grave_,
+% y.hook_,
+% y.tilde_,
+last
+enddef;
+%</test>
+% \end{macrocode}
+% \end{multicols}
+%
+% \danger
+% Ta thªm vµo danh s¸ch trªn ch÷ c¸i ¶o |last|. \emph{Môc ®Ých:}
+% Khi dïng vßng lÆp |for| ®Ó duyÖt qua danh s¸ch
+% |testchars|, ta ph¶i biÕt lóc nµo th× kÕt thóc danh s¸ch.
+% Ch÷ c¸i ¶o |last| t¹o ®iÒu kiÖn ®Ó kiÓm tra.
+% Nh vËy, |last| ph¶i lu«n ®îc |test|:
+% ta kh«ng ®îc phÐp bá ®i |last| trong danh s¸ch nãi trªn.
+% \endanger
+%
+% \begin{macrocode}
+%<test> C.l.last := C.u.last := 256;
+% \end{macrocode}
+%
+% \subsection{Test: Macros}
+%
+% \begin{macro}{used_char}
+% Macro nµy kiÓm tra xem \meta{char} víi m· |_code| cã n»m trong
+% danh s¸ch |testchars| hay kh«ng. NÕu cã, \meta{char} nµy sÏ ®îc vÏ.
+% ChØ trong \tstmode\ míi cã sù kiÓm tra nµy, cßn trong b¶n
+% \meta{publish} cña |VNR-METAFONT| th× macro |used_char| ®îc bá qua.
+% Xem ®Þnh nghÜa cña macro |define_vnchar| (\lref{def:define_vnchar}).
+% \begin{macrocode}
+%<*test>
+vardef used_char(expr _code) =
+%<=def:used_char>
+ boolean _is_used;
+ if not known test_all_chars:
+ _is_used := false;
+ forsuffixes $ = testchars:
+ if _code = vn_code($):
+ _is_used := true;
+ fi;
+ endfor;
+ else:
+ _is_used := true;
+ fi;
+ _is_used
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% Khai b¸o 14 biÕn kiÓu |BOOLEAN|.
+% C¸c biÕn nµy ®îc g¸n gi¸ trÞ ban ®Çu |FALSE|.
+%
+% \emph{VÝ dô:} biÕn |a_fam_used| cã gi¸ trÞ |TRUE| nÕu mét trong c¸c
+% ch÷ c¸i |a|, |¸|, |µ|, |¶|, |·|, |¹| ®îc |test|. Lu ý r»ng,
+% c¸c ch÷ c¸i |a|, |¸|, |µ|, |¶|, |·|, |¹| ®îc vÏ theo c¸ch \emph{t¬ng
+% tù} nhau, nªn ta chØ cÇn \emph{dïng mét biÕn} lµ |a_fam_used|:
+% nÕu |a_fam_used| b»ng |TRUE|, th× ta sÏ |load| m· |MF| ®Ó vÏ c¸c
+% ch÷ |a|, m· nµy ®Æt trong |vnlar|.
+%
+% Xem thªm ®Þnh nghÜa cña |input_lr_fam|, |input_ur_fam| bªn díi.
+%
+% \begin{macrocode}
+%<*test>
+forsuffixes _u =
+ A_fam_used, D_fam_used, E_fam_used, I_fam_used,
+ O_fam_used, U_fam_used, Y_fam_used,
+ a_fam_used, d_fam_used, e_fam_used, i_fam_used,
+ o_fam_used, u_fam_used, y_fam_used:
+ boolean _u;
+ _u := false;
+endfor;
+%</test>
+% \end{macrocode}
+%
+% Gi¶ sö trong |test_char|, \meta{char} cã m· |_c| ®îc \meta{test}.
+% Khi ®ã, ta sÏ t×m xem \meta{char} nµy n»m trong hä nµo (|A_fam|,
+% |e_fam|, v.v...). NÕu (vÝ dô) nã n»m trong hä |a_fam|, th× ta sÏ g¸n
+% biÕn |a_fam_used| gi¸ trÞ |TRUE|.
+%
+% \begin{macro}{test_fam}
+%
+% Macro |test_fam| díi ®©y cã nhiÖm
+% vô tr¶ lêi xem \meta{char} víi m· |_c| cã n»m trong hä |_f| hay kh«ng;
+% nÕu cã th× g¸n |_u| b»ng |TRUE|. \emph{Lu ý:} c¸c \meta{char} (tiÕng
+% ViÖt) chØ cã m· hoÆc nhá h¬n |32|, hoÆc lín h¬n |127|.
+%
+% \begin{macrocode}
+%<*test>
+def test_fam(text _f, _u, _c) =
+ n_ := 0;
+ if not _u:
+ forsuffixes $ = _f(,) 257:
+ n_ := n_ + 1;
+ if (($ < 32) or ($ > 127)) and ($ = C.u._c) or ($ = C.l._c):
+ _u := true;
+ fi
+ endfor
+ fi
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% B©y giê, ta duyÖt qua tÊt c¶ c¸c hä (ch÷ hoa) ®Ó xem |_c| thuéc hä nµo.
+% Râ rµng, mçi \meta{char} chØ thuéc mét vµ chØ mét hä mµ th«i, nªn ta cã
+% thÓ c¶i thiÖn viÖc duyÖt b»ng c¸ch dïng |if...elif...if|. (Nhng viÖc
+% nµy kh«ng \emph{kinh tÕ}l¾m.)
+%
+% \begin{multicols}2
+% \begin{macrocode}
+%<*test>
+forsuffixes _c = testchars:
+ test_fam(A_fam)(A_fam_used)(_c);
+ test_fam(D_fam)(D_fam_used)(_c);
+ test_fam(E_fam)(E_fam_used)(_c);
+ test_fam(I_fam)(I_fam_used)(_c);
+ test_fam(O_fam)(O_fam_used)(_c);
+ test_fam(U_fam)(U_fam_used)(_c);
+ test_fam(Y_fam)(Y_fam_used)(_c);
+ test_fam(a_fam)(a_fam_used)(_c);
+ test_fam(d_fam)(d_fam_used)(_c);
+ test_fam(e_fam)(e_fam_used)(_c);
+ test_fam(i_fam)(i_fam_used)(_c);
+ test_fam(o_fam)(o_fam_used)(_c);
+ test_fam(u_fam)(u_fam_used)(_c);
+ test_fam(y_fam)(y_fam_used)(_c);
+ test_fam(U_horn_fam)(U_fam_used)(_c);
+ test_fam(u_horn_fam)(u_fam_used)(_c);
+endfor
+%</test>
+% \end{macrocode}
+% \end{multicols}
+%
+% BiÕn |inpustr| ®îc dïng trong 4 macro s¾p tíi.
+%
+% \begin{macrocode}
+%<test>string inputstr;
+% \end{macrocode}
+%
+% \begin{macro}{input_ur_fam}
+% Xem hä ch÷ nµo ®îc dïng th× |load| m· |MF| ®Ó vÏ hä t¬ng øng.
+% \up ë ®©y lµ hä c¸c ch÷ hoa.
+% \begin{macrocode}
+%<*test>
+def input_ur_fam =
+ inputstr := "";
+ if A_fam_used: inputstr := inputstr & "input vnuar; "; fi
+ if D_fam_used: inputstr := inputstr & "input vnudr; "; fi
+ if E_fam_used: inputstr := inputstr & "input vnuer; "; fi
+ if I_fam_used: inputstr := inputstr & "input vnuir; "; fi
+ if O_fam_used: inputstr := inputstr & "input vnuor; "; fi
+ if U_fam_used: inputstr := inputstr & "input vnuur; "; fi
+ if Y_fam_used: inputstr := inputstr & "input vnuyr; "; fi
+ scantokens(inputstr);
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{input_lr_fam}
+% |Load| m· vÏ c¸c ch÷ thêng.
+% \begin{macrocode}
+%<*test>
+def input_lr_fam =
+ inputstr := "";
+ if a_fam_used: inputstr := inputstr & "input vnlar; "; fi
+ if d_fam_used: inputstr := inputstr & "input vnldr; "; fi
+ if e_fam_used: inputstr := inputstr & "input vnler; "; fi
+ if i_fam_used: inputstr := inputstr & "input vnlir; "; fi
+ if o_fam_used: inputstr := inputstr & "input vnlor; "; fi
+ if u_fam_used: inputstr := inputstr & "input vnlur; "; fi
+ if y_fam_used: inputstr := inputstr & "input vnlyr; "; fi
+ scantokens(inputstr);
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{input_sc_fam}
+% |Load| m· vÏ c¸c ch÷ |small-cap|.
+% \begin{macrocode}
+%<*test>
+def input_sc_fam =
+ inputstr := "";
+ if a_fam_used: inputstr := inputstr & "input vnuar; "; fi
+ if d_fam_used: inputstr := inputstr & "input vnudr; "; fi
+ if e_fam_used: inputstr := inputstr & "input vnuer; "; fi
+ if i_fam_used: inputstr := inputstr & "input vnuir; "; fi
+ if o_fam_used: inputstr := inputstr & "input vnuor; "; fi
+ if u_fam_used: inputstr := inputstr & "input vnuur; "; fi
+ if y_fam_used: inputstr := inputstr & "input vnuyr; "; fi
+ scantokens(inputstr);
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{input_li_fam}
+% |Load| m· vÏ c¸c ch÷ nghiªng.
+% \begin{macrocode}
+%<*test>
+def input_li_fam =
+ inputstr := "";
+ if a_fam_used: inputstr := inputstr & "input vnlai; "; fi
+ if d_fam_used: inputstr := inputstr & "input vnldi; "; fi
+ if e_fam_used: inputstr := inputstr & "input vnlei; "; fi
+ if i_fam_used: inputstr := inputstr & "input vnlii; "; fi
+ if o_fam_used: inputstr := inputstr & "input vnloi; "; fi
+ if u_fam_used: inputstr := inputstr & "input vnlui; "; fi
+ if y_fam_used: inputstr := inputstr & "input vnlyi; "; fi
+ scantokens(inputstr);
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{bboxcolor}
+% \begin{macro}{bbxorule}
+% Macro |bboxrule| dïng ®Ó vÏ ®o¹n th¼ng nèi hai ®iÓm |w| vµ |z|,
+% víi mµu lµ |bboxcolor| vµ kiÓu ®êng th¼ng lµ |linecap|.
+% \emph{Lu ý:} |linecap| lµ biÕn |internal| cña |MetaPOST|.
+%
+% \danger
+% NÕu ta muèn t¹m thêi quªn ®i gi¸ trÞ cña mét biÕn |internal|, ë ®©y lµ
+% biÕn |linecap|, th× dïng |interim| trong mét |group|. Sau |group| ®ã,
+% gi¸ trÞ cò cña biÕn |internal| sÏ ®îc phôc håi. §èi víi biÕn |external|,
+% ta dïng hµm |save| thay v× |interim|.
+% \endanger
+% \begin{macrocode}
+%<*test>
+def bboxcolor = red enddef;
+def bboxrule(expr w,z) =
+ begingroup
+ interim linecap := squared;
+ draw w..z
+ withpen pencircle scaled (.4/bp_per_pixel)
+ withcolor bboxcolor;
+ endgroup
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{makebbox}
+% VÏ bèn c¹nh cña h×nh ch÷ nhËt bao quanh \meta{h×nh vÏ}
+% víi kÝch thíc cña h×nh ch÷ nhËt b»ng kÝch thíc cña \meta{h×nh vÏ}.
+% \meta{H×nh vÏ} ë ®©y lµ \meta{char} hoÆc \meta{accent}.
+% \begin{macrocode}
+%<*test>
+def makebbox(text rule) =
+ if known makeXbox:
+ for x = 0,w:
+ bboxrule((x,-d),(x,h)); endfor
+ for y = 0,h,-d:
+ bboxrule((0,y),(w,y)); endfor
+ fi
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{makebox}
+% VÏ líi gåm c¸c ®o¹n th¼ng ®i qua c¸c ®iÓm ®Æc biÖt.
+% \danger
+% Macro nµy dïng ®Ó kÕt thóc viÖc vÏ \meta{char},
+% kh«ng dïng ®Ó kÕt thóc viÖc vÏ \meta{accent}.\\
+% Cã thÓ xem chó thÝch vÒ macro nµy trong \mfb E/309/.
+% \endanger
+% \begin{macrocode}
+%<*test>
+def makebox(text rule) =
+% \end{macrocode}
+% VÏ b¶y (7) ®êng th¼ng n»m ngang: mét ®êng ®i qua gèc täa ®é;
+% mét ®êng ®i ë ®é s©u |body_depth| -- ®êng nµy kh«ng thÓ thÊy ®îc
+% nÕu ta xem kÕt qu¶ do viÖc |merge| c¸c file "PS" t¹o bëi "MetaPost".
+% \begin{macrocode}
+ for y = 0, (cap_height+acc_height),
+ asc_height, body_height, x_height,
+ bar_height, desc_depth ,-body_depth:
+ rule((l,y),(r,y));
+ endfor
+% \end{macrocode}
+% \begin{macrocode}
+ for y = -3.5pt, 8.5pt, (x_height + acc_height):
+ rule((l-4pt,y),(l-2pt,y));
+ endfor
+% \end{macrocode}
+% VÏ c¸c ®êng th¼ng ®øng.
+% \begin{macrocode}
+ for x=l,r:
+ rule((x,-body_depth),(x,body_height));
+ endfor
+% \end{macrocode}
+% VÏ c¸c ®êng th¼ng ®øng phô.
+% \begin{macrocode}
+ for x = u*(1 + floor(l/u)) step u until r-1:
+ rule((x,-body_depth),(x,body_height));
+ endfor
+ for x = 0.5w:
+ rule((x,-body_depth - 1pt),
+ (x,-body_depth - 1.5pt));
+ rule((x, cap_height + acc_height + 1pt),
+ (x, cap_height + acc_height + 1.5pt));
+ endfor
+% \end{macrocode}
+% VÏ thªm ®êng th¼ng ®øng nÕu |charic <> 0|.
+% \begin{macrocode}
+ if charic <> 0:
+ rule((r + charic*pt, h.o_),
+ (r + charic*pt,.5h.o_));
+ fi
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Test: enchar}
+%
+% \begin{macro}{endchar}
+% Sau khi kÕt thóc viÖc vÏ mét \meta{char},
+% ta vÏ h×nh ch÷ nhËt bao quanh \meta{char} ®ã (b»ng |makebbox|),
+% vµ vÏ líi gåm c¸c ®êng th¼ng ®Æc biÖt (b»ng |makebox|).
+%
+% \danger
+% Xem trong |METAFONTBook| vÒ |proofrule|.
+% \endanger
+% \begin{macrocode}
+%<*test>
+def endchar =
+ scantokens extra_endchar;
+% if proofing > 0:
+ if known makeXbox:
+ makebox(proofrule);
+ makebbox(proofrule);
+ fi
+ shipit;
+ endgroup
+enddef;
+%</test>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Writting Shifting Information}
+%
+% \begin{macro}{abs_round}
+% \begin{macrocode}
+%<*t5supp>
+def abs_round(expr _e) =
+ if _e < 0: ceiling(_e - .5)
+ else: floor(_e + .5)
+ fi
+enddef;
+%</t5supp>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{write_shift_xy}
+% Ghi ra *log* file th«ng tin vÒ |shift|; c¸c th«ng tin nµy ®îc sö dông
+% trong qu¸ tr×nh chuyÓn font *VNR* sang *type1* format.
+% Xem \href{../doc/vnr_type1.pdf}{vnr_type1.pdf} (appendix {\bf A})
+% ®Ó biÕt thªm vai trß cña macro nµy.
+% \begin{macrocode}
+%<*t5supp>
+def write_shift_xy(suffix _l, _a)(expr _sx, _sy) =
+ if known bp_per_pixel:
+ message "CC " &
+ if case_ = capital: "capital"
+ elseif case_ = small: "small"
+ else: "smallcap"
+ fi & " " & str _l & " " & str _a & " " &
+ decimal(abs_round(_sx*bp_per_pixel*10/designsize)) & " " &
+ decimal(abs_round(_sy*bp_per_pixel*10/designsize));
+ fi
+enddef;
+%</t5supp>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Miscellanea}
+%
+% BiÕn |case_| dïng lµm |switch| ®Ó x¸c ®Þnh kiÓu ch÷ hoa/thêng/...
+% \begin{macrocode}
+numeric case_;
+small := 0;
+capital := 1;
+smallcap := 2;
+def set_lowercase =
+ case_ := small;
+ def vncase = l enddef;
+enddef;
+def set_uppercase =
+ case_ := capital;
+ def vncase = u enddef;
+enddef;
+def set_smallcap =
+ case_ := smallcap;
+ def vncase = l enddef;
+enddef;
+% \end{macrocode}
+%
+% \begin{macro}{casename}
+% Tªn ®Çy ®ñ cña ch÷ c¸i ®ang ®îc
+% |METAFONT| vÏ (chØ khi |testing| lµ \emph{unknown}).
+% Cã thÓ thÊy c¸c tªn nµy trªn |terminal| vµ trong file |log|
+% nÕu ch¹y |mf| víi |mode := proof|.
+% \begin{macrocode}
+def casename expr _name =
+%<*!test>
+ "The " &
+ if case_ = capital: "capital"
+ elseif case_ = small: "small"
+ else: "smallcap" fi
+ & " letter " & _name
+%</!test>
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{ifknown}
+% This macro expands to |_b| if the suffix |_a| is \emph{unknown},
+% and to |_a| itself in the other case.
+% Macro nµy ®îc dïng nhiÒu, khi ph¶i lùa chän c¸c biÕn t¬ng øng
+% víi c¸c dÊu. Xem mét vÝ dô ë \lref{use:ifknown}.
+% \begin{macrocode}
+def ifknown(suffix _a)(expr _b) =
+ if known _a: _a else: _b fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{tand}
+% Hµm tÝnh |tangent| cña gãc |d| (tÝnh b»ng ®é, |d = degree|).
+% \begin{macrocode}
+def tand(expr _d) =
+ (sind(_d)/cosd(_d))
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{hp}
+% Lµm trßn theo chiÒu ngang (|horizontal|).
+% \begin{macrocode}
+def hp(expr _x) =
+ hround(_x*hppp)
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{vp}
+% Lµm trßn theo chiÒu ®øng (|vertical|).
+% \begin{macrocode}
+def vp(expr _y) =
+ vround(_y*vppp)
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Macro: begin, end}
+%
+% \begin{macro}{begin_pic}
+% \begin{macrocode}
+def begin_pic(suffix _n) =
+ begingroup
+ clearxy;
+ clearit;
+ clearpen;
+ picture vn.vncase._n.pic;
+ vn.vncase._n.pic :=
+ begingroup
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{end_pic}
+% \begin{macrocode}
+def end_pic =
+% \end{macrocode}
+%
+% \danger
+% Ta chØ cã thÓ dïng |makebbox| ë ®©y mµ th«i!
+% \endanger
+%
+% \begin{macrocode}
+%<test> makebbox(proofrule);
+% \end{macrocode}
+%
+% \begin{macrocode}
+ currentpicture
+ endgroup;
+ endgroup
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+let end_accent = end_pic;
+let begin_letter = begin_pic;
+let end_letter = end_pic;
+% \end{macrocode}
+%
+% \begin{macro}{begin_accent}
+% \begin{macrocode}
+def begin_accent(suffix _a) =
+ begin_pic(_a);
+ set_char_dimens(vn_width(_a), vn_height(_a), 0)
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Picture's Properties}
+%
+% Tõ \meta{h×nh vÏ} dïng ®Ó chØ \meta{picture} do |METAFONT|
+% t¹o ra khi vÏ ch÷ c¸i \meta{char}, hoÆc dÊu \meta{accent}.
+% Mçi \meta{h×nh vÏ} cã c¸c thuéc tÝnh sau ®©y:
+% \begin{verbatim}
+% code, pic, width, height, top, bot, depth,
+% ic, left, right, gap, join_xp, join_x
+% \end{verbatim}
+%
+% \begin{multicols}2
+% \begin{macrocode}
+def vn_code(suffix _n) =
+ C.vncase._n
+enddef;
+def vn_pic(suffix _n) =
+ vn.vncase._n.pic
+enddef;
+def vn_width(suffix _n) =
+ vn.vncase._n.w#
+enddef;
+def vn_height(suffix _n) =
+ vn.vncase._n.h#
+enddef;
+def vn_top(suffix _n) =
+ vn.vncase._n.top#
+enddef;
+def vn_depth(suffix _n) =
+ vn.vncase._n.d#
+enddef;
+def vn_bot(suffix _n) =
+ vn.vncase._n.bot#
+enddef;
+def vn_ic(suffix _n) =
+ vn.vncase._n.ic#
+enddef;
+def vn_left_adj(suffix _n) =
+ vn.vncase._n.left_adj#
+enddef;
+def vn_right_adj(suffix _n) =
+ vn.vncase._n.right_adj#
+enddef;
+def vn_gap(suffix _n) =
+ vn.vncase._n.gap#
+enddef;
+def vn_join_xp(suffix _n) =
+ vn.vncase._n.join.x
+enddef;
+def vn_join_x(suffix _n) =
+ vn.vncase._n.join.x#
+enddef;
+def vn_rt(suffix _n) =
+ vn.vncase._n.rt#
+enddef;
+def vn_dot_shift_y(suffix _n) =
+ vn.vncase._n.dot_shift.y#
+enddef;
+def vn_ac_top =
+ vn.vncase.accent_top#
+enddef;
+def vn_double_ac_top =
+ vn.vncase.double_accent_top#
+enddef;
+let vn_left_side = vn_join_x;
+def vn_right_side(suffix _a) =
+ (vn_width(_a) - vn_left_side(_a))
+enddef;
+def align_left(suffix _a, _b) =
+ 0
+enddef;
+def vn_align_join(suffix _a, _b) =
+ (vn_join_x(_a) - vn_join_x(_b))
+enddef;
+def vn_align_right(suffix _a, _b) =
+ (vn_width(_a) - vn_width(_b))
+enddef;
+% \end{macrocode}
+% \end{multicols}
+%
+% \subsection{Setting Macros}
+%
+% \begin{macro}{define_accent_dimens}
+% X¸c ®Þnh c¸c kÝch thíc cña mét dÊu (gåm cã |width|, |height|, |top|).
+% \begin{macrocode}
+def define_accent_dimens(suffix _a)(expr _w, _h) =
+ vn_width(_a) := _w;
+ vn_height(_a) := _h;
+ vn_top(_a) := vn_height(_a) + vn_letter_height# + vn_accent_gap#;
+% \end{macrocode}
+% TÝnh l¹i gi¸ trÞ lín nhÊt cña |vn_max_ac_top#|.
+% \begin{macrocode}
+ vn_max_ac_top# := max(vn_max_ac_top#, vn_top(_a));
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_char_dimens}
+% \begin{macrocode}
+def set_char_dimens(expr _w, _h, _d) =
+ charwd := _w;
+ charht := _h;
+ chardp := _d;
+ w := hp(charwd);
+ h := vp(charht);
+ d := vp(chardp);
+ charic := 0;
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_letter_dimens}
+% \begin{macrocode}
+def set_letter_dimens(suffix _l)(expr _w, _h, _d, _ic, _lft, _rt) =
+ set_char_dimens(_w, _h, _d);
+ vn_width(_l) := _w;
+ vn_height(_l) := _h;
+ vn_depth(_l) := _d;
+ vn_ic(_l) := _ic;
+ vn_left_adj(_l) := _lft;
+ vn_right_adj(_l) := _rt;
+ adjust_fit(_lft, _rt);
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_ac_join}
+% \begin{macrocode}
+def set_ac_join(suffix _a)(expr _xp, _x, _rt) =
+ vn_join_xp(_a) := _xp;
+ vn_join_x(_a) := _x;
+ vn_rt(_a) := _rt;
+%<*test>
+ if known show_labels:
+ makelabel("j", (vn_join_xp(_a), 0));
+ makelabel("J", (hp(vn_join_x(_a)), 0));
+ makelabel("r", (hp(vn_width(_a)), vp(vn_rt(_a))));
+ makelabel("o", (0,0));
+ fi;
+%</test>
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_letter_join}
+% \begin{macrocode}
+def set_letter_join(suffix _l)(expr _xp, _x) =
+ vn_join_xp(_l) := _xp;
+ vn_join_x(_l) := _x;
+%<*test>
+ if known show_labels:
+ makelabel("X", (vn_join_xp(_l), vp(vn_height(_l))));
+ makelabel("Y", (hp(vn_join_x(_l)), vp(vn_height(_l))));
+ fi;
+%</test>
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_adj_gap}
+% \begin{macrocode}
+def set_adj_gap(suffix _l, _a) =
+%<=use:ifknown>
+ adj_gap# := ifknown(vn_gap(_l._a),
+ ifknown(vn_gap(_a), 0));
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_shift}
+% \begin{macrocode}
+def set_shift(suffix _l, _a) =
+ shift.y := vp(vn_top(_a) - vn_height(_a))
+ + ifknown(hook_shift.y._l._a,0)*u;
+ shift.x := get_join_xp(_l, _a) - vn_join_xp(_a)
+ + slant*shift.y
+ + ifknown(hook_shift.x.vncase._l._a,0)*u;
+% \end{macrocode}
+%
+% \begin{macrocode}
+ shift.y# := vn_top(_a) - vn_height(_a)
+ + ifknown(hook_shift.y._l._a#,0)*u#;
+ shift.x# := get_join_x(_l, _a) - vn_join_x(_a)
+ + slant*shift.y#
+ + ifknown(hook_shift.x.vncase._l._a#,0)*u#;
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_ic}
+% \begin{macrocode}
+def set_ic(suffix _l, _a) =
+ italcorr max(vn_ic(_l),
+ vn_width(_a) + shift.x#
+ + slant*(vn_rt(_a) + shift.y#)
+ - w# + .5u#);
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_lic}
+% \begin{macrocode}
+def set_lic(suffix _l) =
+ italcorr vn_ic(_l);
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_fit}
+% \begin{macrocode}
+def set_fit(suffix _l) =
+ adjust_fit(vn_left_adj(_l), vn_right_adj(_l));
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_dot_shift}
+% to avoid error when calling |set_dot_shift(idot)|
+% \begin{macrocode}
+C.l.idot.dot_ = C.u.idot.dot_ = 256;
+% \end{macrocode}
+%
+% \begin{macrocode}
+def set_dot_shift(suffix _l) =
+ shift.y := - vp(ifknown(vn_dot_shift_y(_l), vn_bot(dot_)));
+ shift.x := get_join_xp(_l, dot_) - vn_join_xp(dot_) + slant*shift.y;
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Getting Macros}
+%
+% \begin{macro}{get_join_xp}
+% \begin{macrocode}
+def get_join_xp(suffix _l, _a) =
+ ifknown(vn_join_xp(_l._a), vn_join_xp(_l))
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{get_join_x}
+% \begin{macrocode}
+def get_join_x(suffix _l, _a) =
+ ifknown(vn_join_x(_l._a), vn_join_x(_l))
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{get_top}
+% \begin{macrocode}
+def get_top(suffix _a) =
+%<=def:get_top>
+ max(vn_top(_a) + adj_gap#,
+ if vn_top(_a) <= vn_ac_top:
+ vn_ac_top
+ else:
+ vn_double_ac_top
+ fi)
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Pos Function}
+%
+% \begin{macro}{pos}
+% Xem chó thÝch trong \mfb E/310/.
+% \begin{macrocode}
+vardef pos@#(expr b,d) =
+ if known b:
+ if b <= currentbreadth:
+ (x@#r - x@#l, y@#r - y@#l) = (eps,0) rotated d;
+ else: (x@#r - x@#l, y@#r - y@#l) = (b - currentbreadth, 0) rotated d;
+ fi
+ else: (x@#r - x@#l, y@#r - y@#l) = (b - currentbreadth, 0) rotated d;
+ fi
+% \end{macrocode}
+% H×nh nh anh Thµnh nhÇm lÉn, khi dïng *|if known b ... else|*?
+% Kh«ng! Quan s¸t file *log* (sau khi thªm *message ...* vµo trong *else:*)
+% ta thÊy cã nhiÒu lÇn trêng hîp "else" x¶y ra... Xem xÐt mét sè trêng hîp
+% gäi *pos*, ta thÊy: cã khi *|expr b|* lµ mét biÓu thøc,
+% cã khi nã lµ mét biÕn. VÝ dô, khi vÏ *tilde* trong *vnaccent*,
+% anh Thµnh ®· dïng\\\centerline{"pos1(vn_tilde_vair, theta + 90)"}
+% Nh vËy lµ, hµm *pos* ®îc ®Þnh nghÜa ë ®©y \emph{rÊt m¹nh}.
+% Mét c©u hái ®Æt ra lµ, liÖu cã cÇn ph©n biÖt hai trêng hîp nh trªn?
+% C©u tr¶ lêi lµ \emph{kh¼ng ®Þnh}.
+% \up ý cña anh Thµnh lµ: nÕu *|expr b|* ®îc dïng lµ mét biÕn, th× cÇn
+% ph¶i khèng chÕ trêng hîp gi¸ trÞ cña biÕn ®ã ë díi ngìng cho phÐp!
+% \begin{macrocode}
+ x@# = .5(x@#l + x@#r);
+ y@# = .5(y@#l + y@#r)
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{vn_sl_shift}
+% \begin{macrocode}
+def vn_sl_shift(suffix _a) =
+% .5slant*(adj_y# + vn_height(_a))
+ 0
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Drawing Letters and Accents}
+%
+% \begin{macro}{define_vnchar}
+% \label{def:define_vnchar}
+%
+% Macro nµy nèi dÊu |_c| víi ch÷ |_c|, t¹o thµnh mét ch÷ c¸i
+% tiÕng ViÖt. VÝ dô, nèi dÊu huyÒn víi ch÷ "a".
+%
+% \begin{macrocode}
+def define_vnchar(suffix _l, _a) =
+%<=def:define_vnchar>
+%<test> if used_char(vn_code(_l._a)):
+ set_adj_gap(_l, _a);
+ beginchar(vn_code(_l._a),
+ vn_width(_l),
+ get_top(_a),
+ vn_depth(_l));
+ set_shift(_l, _a);
+ set_ic(_l, _a);
+ set_fit(_l);
+ currentpicture := vn_pic(_l);
+ addto currentpicture also vn_pic(_a)
+ shifted (shift.x, shift.y + vp(adj_gap#));
+%<*t5supp>
+ write_shift_xy(_l, _a)
+ (shift.x + hp(vn_left_adj(_l)) + letter_fit,
+ shift.y + vp(adj_gap#));
+%</t5supp>
+ endchar
+%<test> fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{define_double_accent}
+% \begin{macrocode}
+def define_double_accent(suffix _a, _b)(expr _adj_x, _adj_y) =
+ shift.y# := _adj_y + vn_height(_a);
+ shift.x# := _adj_x + slant*shift.y#;
+ define_accent_dimens(_a._b, vn_width(_a), vn_height(_b) + shift.y#);
+ begin_accent(_a._b);
+ currentpicture := vn_pic(_a);
+ addto currentpicture
+ also vn_pic(_b) shifted (hp(shift.x#), vp(shift.y#));
+%<*t5supp>
+ write_shift_xy(_a, _b)(hp(shift.x#), vp(shift.y#));
+%</t5supp>
+ set_ac_join(
+ _a._b,
+ vn_join_xp(_a),
+ vn_join_x(_a),
+ if vn_width(_a) + slant*vn_rt(_a)
+ > vn_width(_b) + shift.x#
+ + slant*(vn_rt(_b) + shift.y#):
+ vn_rt(_a)
+ else:
+ vn_rt(_b) + shift.y#
+ fi);
+ end_accent;
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{define_vnaccent}
+%
+% VÏ \meta{accent} |_a| víi m· |_c|.
+% ChØ dïng víi |T5supp|.
+% Xem c¸ch dïng trong *vnuacc* \lref{use:define_vnaccent}.
+%
+% \begin{macrocode}
+%<*t5supp>
+def define_vnaccent(expr _c)(suffix _a) =
+%<=def:define_vnaccent>
+ beginchar(_c, vn_width(_a), vn_height(_a), 0);
+ currentpicture := vn_pic(_a);
+ endchar
+enddef;
+%</t5supp>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{define_vnchar_dot}
+%
+% Thªm dÊu nÆng vµo mét ch÷
+%
+% \begin{macrocode}
+def define_vnchar_dot(suffix _l) =
+%<test> if used_char(vn_code(_l.dot_)):
+% \end{macrocode}
+% Ta ph©n biÖt hai trêng hîp: ch÷ |Þ| (thêng)
+% vµ c¸c ch÷ kh¸c (víi dÊu nÆng).
+% \begin{macrocode}
+ if (case_ = small) and (vn_code(_l.dot_) = vn_code(i.dot_)):
+ beginchar(vn_code(i.dot_),
+ vn_width(idot),
+ vn_height(idot),
+ vn_bot(dot_));
+ set_dot_shift(idot);
+ set_lic(idot);
+ set_fit(idot);
+ currentpicture := vn_pic(idot);
+ else:
+ beginchar(vn_code(_l.dot_),
+ vn_width(_l),
+ vn_height(_l),
+ ifknown(vn_depth(_l.dot_),
+ max(vn_bot(dot_), vn_depth(_l))));
+ set_dot_shift(_l);
+ set_lic(_l);
+ set_fit(_l);
+ currentpicture := vn_pic(_l);
+ fi
+ addto currentpicture
+ also vn_pic(dot_) shifted (shift.x, shift.y);
+%<*t5supp>
+ write_shift_xy(_l, dot_)
+ (shift.x + hp(vn_left_adj(_l)) + letter_fit,
+ shift.y);
+%</t5supp>
+ endchar
+%<test> fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{define_vnchar_dot_ac}
+%
+% Thªm dÊu vµ dÊu nÆng vµo mét ch÷ cã dÊu.
+%
+% \begin{macrocode}
+def define_vnchar_dot_ac(suffix _l, _a) =
+%<test> if used_char(vn_code(_l._a.dot_)):
+ set_adj_gap(_l, _a);
+ beginchar(vn_code(_l._a.dot_),
+ vn_width(_l),
+ get_top(_a),
+ max(vn_bot(dot_), vn_depth(_l)));
+ set_shift(_l, _a);
+ set_ic(_l, _a);
+ set_fit(_l);
+ currentpicture := vn_pic(_l);
+ addto currentpicture
+ also vn_pic(_a) shifted (shift.x, shift.y + vp(adj_gap#));
+ set_dot_shift(_l);
+ addto currentpicture
+ also vn_pic(dot_) shifted (shift.x, shift.y);
+%<*t5supp>
+ write_shift_xy(_l._a, dot_)
+ (shift.x + hp(vn_left_adj(_l)) + letter_fit, shift.y);
+%</t5supp>
+ endchar
+%<test> fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{define_vnchar_horn}
+%
+% VÏ r©u cho ch÷ |u| hoÆc |o|.
+%
+% \begin{macrocode}
+def define_vnchar_horn(suffix _l) =
+%<test> if used_char(vn_code(_l.horn_)):
+ select_horn(_l);
+ set_shift_horn(_l);
+ update_horn_width(_l);
+ beginchar(vn_code(_l.horn_),
+ updated_width#,
+ vn_top(cur_horn_),
+ vn_depth(_l));
+ set_ic(_l, cur_horn_);
+ set_fit(_l);
+ select_letter_u(_l);
+ addto currentpicture
+ also vn_pic(cur_horn_) shifted (shift.x, shift.y);
+ endchar
+%<test> fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{select_horn}
+%
+% Chän r©u cña ch÷ |u| hay ch÷ |o|.
+%
+% \begin{macrocode}
+def select_horn(suffix _l) =
+ if vn_code(_l.horn_) = vn_code(u.horn_):
+ def cur_horn_ = uhorn_ enddef;
+ else: def cur_horn_ = ohorn_ enddef;
+ fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{update_horn_width}
+% \begin{macrocode}
+def update_horn_width(suffix _l) =
+ _du := (shift.x + hp(vn_width(cur_horn_)))
+ - (hp(vn_width(_l) + vn_left_adj(_l)
+ + vn_right_adj(_l)) + 2letter_fit)
+ - slant*(shift.y + vp(vn_height(cur_horn_)));
+ updated_width# :=
+ vn_width(_l)
+ if _du > .5u:
+ + .5u#*floor(_du/.5u)
+ fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_shift_horn}
+% \begin{macrocode}
+def set_shift_horn(suffix _l) =
+ shift.y := vp(vn_bot(cur_horn_));
+ shift.x := vn_join_xp(_l.horn_join)
+ - vn_join_xp(cur_horn_) + slant*(shift.y);
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{select_letter_u}
+% \begin{macrocode}
+def select_letter_u(suffix _l) =
+% test for the serif capital u letter with horn
+ if serifs and (case_ <> small) and (vn_code(_l.horn_) = vn_code(u.horn_)):
+% use the modified "U" (without right part of the right serif)
+ currentpicture := vn_pic(Uhorn)
+ else:
+ currentpicture := vn_pic(_l)
+ fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{define_vnchar_horn_ac}
+% set |cur_horn_| to |uhorn_| or |ohorn_| according to |_l|.
+% \begin{macrocode}
+def define_vnchar_horn_ac(suffix _l, _a) =
+%<test> if used_char(vn_code(_l.horn_._a)):
+ select_horn(_l);
+ set_adj_gap(_l, _a);
+ set_shift_horn(_l);
+ update_horn_width(_l);
+ beginchar(vn_code(_l.horn_._a),
+ updated_width#,
+ get_top(_a),
+ vn_depth(_l));
+ set_ic(_l, cur_horn_);
+ set_fit(_l);
+ select_letter_u(_l);
+ addto currentpicture also vn_pic(cur_horn_)
+ shifted (shift.x, shift.y);
+ set_shift(_l.horn_, _a);
+% if serifs and (vn_code(_l.horn_._a) = vn_code(o.horn_.grave_)):
+% shift.x := shift.x + max(0, u - .3stem);
+% fi
+ set_ic(_l, _a);
+ addto currentpicture also vn_pic(_a)
+ shifted (shift.x, shift.y + vp(adj_gap#));
+%<*t5supp>
+ write_shift_xy(_l.horn_, _a)
+ (shift.x + hp(vn_left_adj(_l)) + letter_fit,
+ shift.y + vp(adj_gap#));
+%</t5supp>
+ endchar
+%<test> fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{define_vnchar_horn}
+% \begin{macrocode}
+def define_vnchar_horn_dot(suffix _l) =
+%<test> if used_char(vn_code(_l.horn_.dot_)):
+ select_horn(_l); % set cur_horn_ to uhorn_ or ohorn_ according to _l
+ set_shift_horn(_l);
+ update_horn_width(_l);
+ beginchar(vn_code(_l.horn_.dot_),
+ updated_width#,
+ vn_top(cur_horn_),
+ max(vn_bot(dot_), vn_depth(_l)));
+ set_ic(_l, cur_horn_);
+ set_fit(_l);
+ select_letter_u(_l);
+ addto currentpicture also vn_pic(cur_horn_)
+ shifted (shift.x, shift.y);
+ set_dot_shift(_l);
+ addto currentpicture also vn_pic(dot_)
+ shifted (shift.x, shift.y);
+%<*t5supp>
+ write_shift_xy(_l.horn_, dot_)
+ (shift.x + hp(vn_left_adj(_l)) + letter_fit,
+ shift.y);
+%</t5supp>
+ endchar
+%<test> fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{hook_arck.r}
+% |hook_arc| is based on |super_arc| from exbase.mf
+% \begin{macrocode}
+vardef hook_arc.r(suffix $, $$)(expr _superness, _swap) =
+ pair center, corner;
+ if (y$ = y$r) or _swap:
+ center = (x$$r, y$r);
+ corner = (x$r, y$$r);
+ else:
+ center = (x$r, y$$r);
+ corner = (x$$r, y$r);
+ fi
+ z$.r{corner - z$.r}
+ ... _superness[center, corner]{z$$.r - z$.r}
+ ... {z$$.r - corner}z$$.r
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{hook_arc.l}
+% \begin{macrocode}
+vardef hook_arc.l(suffix $, $$)(expr _superness, _swap) =
+ pair center, corner;
+ if (y$ = y$r) or _swap:
+ center = (x$$l, y$l);
+ corner = (x$l, y$$l);
+ else:
+ center = (x$l, y$$l);
+ corner = (x$$l, y$l);
+ fi
+ z$l{corner - z$l}
+ ... _superness[center, corner]{z$$l - z$l}
+ ... {z$$l - corner}z$$l
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{vn_hook_bulb}
+% |vn_hook_bulb| is based on bulb from |exbase.mf|
+% \begin{macrocode}
+def vn_hook_bulb(suffix $, $$, $$$) =
+ z$$$r = z$$r;
+ path_.l := z$l{x$$r - x$r, 0} ... {0, y$$r - y$r}z$$l;
+ filldraw
+ path.l -- z$$r{0, y$r - y$$r}
+ ... {x$r - x$$r, 0}z$r -- cycle; % link
+ path_.r := z$$$l{0, y$r - y$$r} .. z$$$r{0, y$$r - y$r}; % near - circle
+ filldraw
+ subpath(0, xpart(path_.r intersectiontimes path_.l))
+ of path_.r
+ -- z$$r{0, y$$r - y$r} .. cycle; % bulb
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{vn_draw_horn}
+% \begin{verbatim}
+% ====4r===
+% = 1 = z1r = z4r
+% = = y2 = 1/3[y1, y3]
+% = 4 22l
+% = =
+% = =
+% ===4l====
+% ==
+% ==
+% 3===
+% \end{verbatim}
+%
+% \begin{macrocode}
+def vn_draw_horn(suffix _a)(expr _dotsize, _horn_stem, _horn_bot_theta) =
+ cur_dotsize# := _dotsize;
+ cur_stem# := _horn_stem;
+ define_blacker_pixels(cur_dotsize, cur_stem);
+% \end{macrocode}
+% \begin{macrocode}
+ if not square_dots:
+ pickup crisp.nib;
+ pos4(cur_dotsize, 90);
+ top y4r = h;
+ x4 = w - .5cur_dotsize;
+ pos1(cur_stem, 90);
+ pos2(cur_stem, 0);
+ pos3(cur_stem, _horn_bot_theta - 90);
+ z1r = z4r;
+ rt x2r = hround(x4 + .5cur_dotsize) + 2eps;
+ lft x3l = 0;
+ bot y3r = 0;
+ y2 = 1/3[y1, y3];
+ y_ := ypart( (z1{right} ... z2{down} ... z3 )
+ intersectiontimes (z4l{right} .. {left}z4r) );
+ if y_ < 0:
+ y_ := 1;
+ fi
+% \end{macrocode}
+% Víi ®o¹n m· díi ®©y, ta t« ®îc mét nöa h×nh trßn vµ mét tam gi¸c cong
+% cã mét c¹nh lµ ®êng kÝnh cña nöa h×nh trßn. Tam gi¸c nµy ®îc chän
+% dùa trªn tham sè |y_| ë trªn.
+% {\ttfamily
+% \begin{verbatim}
+% ooooo
+% ooooooox
+% ooooooooxx
+% oooooooooxxx
+% oooooooooxxxx
+% oooooooooxxxxx
+% ooooooooxxxxxxx
+% oooooooxxxxxx
+% ooooooxxxxx
+% ooooxxx
+% \end{verbatim}
+% }
+% \begin{macrocode}
+ filldraw z4r{left}
+ .. subpath (0, y_) of (z4l{right}.. {left}z4r)
+ -- cycle;
+% \end{macrocode}
+% \danger
+% Tuy nhiªn, víi phÇn h×nh trßn ë trªn, khi ®îc phãng to, c¸i r©u sÏ
+% bÞ khuyÕt mét m¶nh.
+%
+% §Ó kh¾c phôc lçi nµy, anh Thµnh ®· thªm vµo mét chót,
+% |--z2--cycle|, trong ®o¹n m· trªn. M¶nh khuyÕt b©y giê kh«ng cßn.
+% Tuy nhiªn, c¸c font |typewriter| khi ®ã ®Òu bÞ lçi <<|strange path|>>.
+% \emph{Lçi nµy xuÊt hiÖn trong bé |VNR| ngµy 2003/03/03
+% (\href{http://vinux.sourceforge.net/vntex}{vinux.sourceforge.net/vntex}).}
+% \endanger
+%
+% TiÕp theo, ta vÏ dÊu phÈy, thªm vµo h×nh ë trªn ®Ó t¹o r©u.
+% \begin{macrocode}
+ filldraw stroke
+ z1e{right} ... z2e{down} ... {left}z3e;
+% \end{macrocode}
+% §Ó che ®i m¶nh khuyÕt ®ång thêi tr¸nh lçi ë trªn,
+% ta cã thÓ viÕt m· riªng... ®Ó t¹o mét tam gi¸c ®ñ lín.
+% C¸c ®Ønh cña tam gi¸c nµy lµ c¸c ®iÓm \meta{ngoµi cïng} cña r©u.
+% Cho ®Õn ngµy "2003/11/30", miÕng v¸ nµy cha thÓ hiÖn thiÕu sãt nµo.
+% C¸c font |typewriter| ®Òu tèt, nhng c¸c font |csc| th× vÉn\footnote{%
+% §· kh¾c phôc lçi sau ®ã mét ngµy, còng víi viÖc viÕt l¹i |docstrip|.
+% \emph{Nguyªn nh©n:} c¸c |guard| trong file
+% *|vndriver.dtx|* lµ c¸c |nested| |guard|, vµ |docstrip.py| khi ®ã
+% kh«ng thÓ hiÓu ®iÒu nµy.}...
+% \danger
+% CÇn xem l¹i |METAFONTbook|, xem thö tam gi¸c nµy liÖu cã ®Ønh *rÊt nhän*
+% hay lµ *trßn* (nh khi dïng |draw|)? (\emph{Tr¶ lêi:} dïng |filldraw|
+% th× chuyÖn nµy khái ph¶i lo....)
+% \endanger
+% \begin{macrocode}
+ filldraw z1r--z2r--z4l--cycle;
+% \end{macrocode}
+% \begin{macrocode}
+%<test> penlabels(0, 1, 2, 3, 4);
+ set_ac_join(_a, x3,
+ .5cur_stem*sind(_horn_bot_theta),
+ h# - .5cur_dotsize#);
+% \end{macrocode}
+% \begin{macrocode}
+ else:
+ pickup fine.nib;
+ pos4(cur_dotsize, 90);
+ top y4r = h;
+ x4 = w - .5cur_dotsize;
+ pos4'(cur_dotsize, 0);
+ z4' = z4;
+ dot(4', 4); % squarish dot
+ horn_join := max(fine.breadth, floor cur_stem);
+ horn_bot := max(fine.breadth, floor .8cur_stem);
+ pos0(horn_join, 0);
+ pos1(horn_join, 0);
+ pos2(horn_bot, 0);
+ y0 = y4;
+ y1 = y4l;
+ x0r = x1r = x4'r;
+ lft x2l = 0;
+ bot y2r = 0;
+ z2' = whatever[z1, z2];
+ numeric _vn_bot_width;
+ pos2'(_vn_bot_width, -90 + _horn_bot_theta);
+ z2l = z2'l;
+ filldraw stroke z0e -- z1e .. z2'e; % tail
+%<test> penlabels(0, 1, 2', 3, 4);
+ set_ac_join(_a, x2', 0, h#);
+ fi
+ vn_bot(_a) := vn_top(_a) - vn_height(_a);
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{set_horn_join}
+% \begin{macrocode}
+def set_horn_join(suffix _l)(expr _pl, _pr) =
+ select_horn(_l); % set cur_horn_ to uhorn_ or ohorn_ according to _l
+ path bot_line;
+ pair L, R;
+ bot_line := (.5w, vp(vn_bot(cur_horn_))) -- (w, vp(vn_bot(cur_horn_)));
+ L := point xpart(bot_line intersectiontimes _pl) of bot_line;
+ R := point xpart(bot_line intersectiontimes _pr) of bot_line;
+ set_ac_join(_l.horn_join, xpart .5[L, R], 0, 0);
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Oct031 Character}
+%
+% \begin{macro}{lig_CGQ_table}
+% \begin{macrocode}
+def lig_CGQ_table(expr k) =
+ "C" kern k, "G" kern k, "Q" kern k
+enddef;
+% \end{macrocode}
+%
+% \begin{macrocode}
+def end_ligtable = 0 kern 0 enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{input_lig}
+% define input_lig to generate only char oct"031" from excspl.mf
+% \begin{macrocode}
+def input_lig suffix @# =
+ let save_endchar = endchar;
+ let endchar = lig_endchar;
+ scantokens("input " & str @#);
+ relax;
+ let endchar = save_endchar;
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{lig_endchar}
+% \begin{macrocode}
+def lig_endchar =
+ if charcode = oct"031":
+ save_endchar
+ else:
+ endgroup
+ fi
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Macro: generate}
+%
+% \begin{macro}{generate}
+% File |vnr10.mf| sÏ |input| c¸c file |vnbase.mf| vµ |ecrm.mf|.
+% §Õn lît m×nh, |ecrm| sÏ |input| driver lµ |exroman| b»ng c¸ch gäi
+% *|generate exroman|* (®èi víi |ec|, |generate| chÝnh lµ |input|).
+% {\tiny
+% \begin{verbatim}
+% 0: 0 *
+% 1: 1 +- vnr10.mf
+% 2: 2 | +- vnbase.mf
+% 3: 3 | | +- exbase.mf
+% 4: 3 | | +- vncode.mf
+% 5: 2 | +- ecrm.mf
+% 6: 3 | | +- null.mf
+% 7: 3 | | +- vnroman.mf
+%
+% (See |doc/vnr10_tree_*.txt| for full detail)
+% \end{verbatim}
+% }
+% §Ó thay thÕ |exroman| b»ng |driver| cña |VNR|, ta sÏ ®Þnh nghÜa l¹i
+% |generate|, nhê vµo ®Æc ®iÓm: c¸c |driver| cña |ec| ®Òu b¾t ®Çu b»ng
+% hai ký tù |ec|, vµ c¸c |driver| cña |VNR| (bao gåm \emph{vnroman},
+% \emph{vncsc}, \emph{vntextit}) ®îc b¾t ®Çu bëi |vn|.
+%
+% \danger
+% Kh«ng thÓ hiÓu t¹i sao ph¶i dïng |scantokens("input null")|.
+% NÕu kh«ng cã dßng nµy, th× tÊt c¶ c¸c file ®Òu ®îc |input| mét
+% c¸ch \emph{b×nh thêng}, nhng kh«ng cã ch÷ nµo ®îc vÏ c¶.
+%
+% T¹i sao anh Thµnh l¹i cã thÓ nghÜ ra chuyÖn thªm dßng nµy vµo?
+% \emph{Qu¸ siªu!}
+% \endanger
+% \begin{macrocode}
+vardef generate @# =
+ scantokens("input null");
+ scantokens("input vn" & substring(2, length(str @#)) of str @#);
+enddef;
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</vnbase>
+% \end{macrocode}
+% \endinput
diff --git a/support/pydocstrip/vndriver.dtx b/support/pydocstrip/vndriver.dtx new file mode 100644 index 0000000000..01f24a8af0 --- /dev/null +++ b/support/pydocstrip/vndriver.dtx @@ -0,0 +1,390 @@ +% \iffalse
+%<dtx>\ProvidesFile{vndriver.dtx}[2003/11/01 v01.01 VNR.KTV.DTX.driver]
+% \fi
+%
+% \section{Driver}
+%
+% \subsection{Common Part}
+%
+% \begin{macrocode}
+%<*test|rm|it|csc>
+% \end{macrocode}
+%
+% |version_check| was introduced in |dc1.3|.
+% \begin{macrocode}
+version_check(1,0);
+% \end{macrocode}
+%
+% Accessories for polish special letters. Pseudoparameters.
+%
+% \begin{macrocode}
+input exaccess;
+input expseudo;
+% \end{macrocode}
+% \begin{macrocode}
+mode_setup;
+font_setup;
+pseudo_setup;
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</test|rm|it|csc>
+% \end{macrocode}
+%
+% \subsection{Test Mode}
+%
+% \begin{macrocode}
+%<test&(rm|it)> set_lowercase;
+%<test&(rm|it)> input vnaccent;
+%<test&rm> input_lr_fam;
+%<test&it> input_li_fam;
+% \end{macrocode}
+% \begin{macrocode}
+%<*test>
+set_uppercase;
+input vnaccent;
+input_ur_fam;
+%</test>
+% \end{macrocode}
+%
+%
+% \subsection{Only for T5supp}
+%
+% \subsubsection{Common Part}
+%
+% \begin{macrocode}
+%<*t5supp>
+input exbraces;
+input expunct;
+%<!csc> input exaccent;
+input exsign;
+%</t5supp>
+% \end{macrocode}
+%
+% \subsubsection{Roman}
+%
+% \begin{macrocode}
+%<*!test&rm&t5supp>
+set_lowercase;
+input vnaccent;
+input vndothook;
+input vnminus;
+input vnlacc;
+input vnclr;
+set_uppercase;
+input vnaccent;
+input vnuacc;
+input vncur;
+%</!test&rm&t5supp>
+% \end{macrocode}
+%
+% \subsubsection{Italic}
+%
+% \begin{macrocode}
+%<*!test&it&t5supp>
+set_lowercase;
+input vnaccent;
+input vndothook;
+input vnminus;
+input vnlacc;
+input vncli;
+set_uppercase;
+input vnaccent;
+input vnuacc;
+input vncur;
+%</!test&it&t5supp>
+% \end{macrocode}
+%
+% \subsubsection{CSC}
+%
+% \begin{macrocode}
+%<*!test&csc&t5supp>
+set_uppercase;
+input vnaccent;
+input vnuacc;
+input vncur;
+%</!test&csc&t5supp>
+% \end{macrocode}
+%
+% If the variable |gen_t5supp_supp| is already known,
+% the |next| equals |endinput| and the driver stops here;
+% otherwise, the |next| is |relax| and nothing happens.
+%
+% \begin{macrocode}
+%<*!test&!t5supp&csc>
+input exrulett;
+input exbraces;
+input expunct;
+input exsign;
+input exromp;
+input exrdigit;
+set_uppercase;
+input vnaccent;
+input vncur;
+%</!test&!t5supp&csc>
+% \end{macrocode}
+%
+% \subsection{Something from EC font}
+%
+% Letters from |EC| font.
+% \begin{macrocode}
+%<*!test&!t5supp&(rm|it)>
+input exbraces;
+input expunct;
+input exaccent;
+input exsign;
+input exrlig;
+input exromp;
+input exrulett;
+input exrllett;
+input exrdigit;
+%</!test&!t5supp&(rm|it)>
+% \end{macrocode}
+%
+% \subsection{Lowercase Letters}
+%
+% \begin{macrocode}
+%<*!test&!t5supp&(rm|it)>
+set_lowercase;
+input vnaccent;
+%</!test&!t5supp&(rm|it)>
+% \end{macrocode}
+%
+% \subsubsection{Roman fonts}
+%
+% \begin{macrocode}
+%<*!test&!t5supp&rm>
+input vnclr;
+input vndothook;
+input vnminus;
+%</!test&!t5supp&rm>
+% \end{macrocode}
+%
+% \subsubsection{Italic fonts}
+%
+% \begin{macrocode}
+%<*!test&!t5supp&it>
+input vncli;
+input vndothook;
+input vnminus;
+%</!test&!t5supp&it>
+% \end{macrocode}
+%
+% \subsection{Uppercase Letters}
+%
+% \begin{macrocode}
+%<*!test&!t5supp&(rm|it)>
+set_uppercase;
+input vnaccent;
+input vncur;
+%</!test&!t5supp&(rm|it)>
+% \end{macrocode}
+%
+% \subsection{Only for CSC}
+%
+% \begin{macrocode}
+%<*csc>
+% \end{macrocode}
+%
+% \begin{macrocode}
+boolean is_small_cap;
+is_small_cap:=true;
+% \end{macrocode}
+%%% fine higher
+% the `higher' values are used while putting accents and attaching ogoneks
+% \begin{macrocode}
+forsuffixes $ =
+ u,o, letter_fit,
+ x_height, bar_height,
+ body_height,stem:
+ higher.$.#:=$.#; higher.$:=$;
+endfor
+% \end{macrocode}
+%%% fine lower
+% \begin{macrocode}
+begingroup
+% \end{macrocode}
+% \begin{macrocode}
+ forsuffixes $ =
+ u, width_adj, cap_serif_fit, letter_fit,
+ body_height, cap_height, x_height, bar_height, comma_depth,
+ flare, dot_size, cap_hair, stem, cap_stem, cap_curve, cap_ess,
+ cap_jut, beak_jut, beak, slab, cap_bar, cap_band, cap_notch_cut,
+ o, apex_o:
+ save $; $.#:=lower.$.#; endfor
+ fudge:=lower.fudge;
+% \end{macrocode}
+% optional part:
+% \begin{macrocode}
+ forsuffixes $ =
+ depth_corr, left_corr, top_breadth_corr,
+ tip_breadth_corr, tip_xcorr, tip_ycorr, pre_angle,
+ post_angle, pre_limit, post_limit, pre_lightness,
+ post_lightness, pre_deflexion, post_deflexion, cap_flat,
+ ogonek_pen#:
+ if known lower.$: $:=lower.$; fi
+ endfor
+% \end{macrocode}
+% \begin{macrocode}
+ input expseudo;
+% \end{macrocode}
+% \begin{macrocode}
+ font_setup;
+ pseudo_setup;
+% \end{macrocode}
+% \begin{macrocode}
+%<*!test&!t5supp>
+ input_lig excspl;
+%</!test&!t5supp>
+% \end{macrocode}
+% \begin{macrocode}
+%<*test>
+ set_smallcap;
+ input vnaccent;
+ input_sc_fam;
+endgroup
+%</test>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*!test&t5supp>
+ set_smallcap;
+ input vnaccent;
+ input vnlacc;
+ input vncur;
+ input txpseudo;
+ font_setup;
+ pseudo_setup;
+ input txaccent;
+ input vndothook;
+ input vnminus;
+% \end{macrocode}
+%
+% \begin{macrocode}
+endgroup
+%</!test&t5supp>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*!test&!t5supp>
+ extra_endchar := extra_endchar & "charcode:=charcode+code_offset";
+ code_offset := ASCII"a" - ASCII"A";
+ input exrulett; % upper case (majuscules)
+ suppress_i_dot := true;
+ code_offset := 0;
+% \end{macrocode}
+% \begin{macrocode}
+ set_smallcap;
+ input vnaccent;
+ input vncur;
+% \end{macrocode}
+% \begin{macrocode}
+ input txpseudo;
+ font_setup;
+ pseudo_setup;
+ input txaccent;
+ input vndothook;
+ input vnminus;
+% \end{macrocode}
+%
+% \begin{macrocode}
+endgroup;
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</!test&!t5supp>
+% \end{macrocode}
+% \begin{macrocode}
+%</csc>
+% \end{macrocode}
+%
+% \subsection{Font Parameters}
+%
+% \subsubsection{Common Part}
+%
+% \begin{macrocode}
+%<*!test&!t5supp&(rm|it|csc)>
+font_coding_scheme := "Vietnamese TeX Font Encoding";
+boundarychar := oct"027";
+font_slant slant;
+font_x_height x_height#;
+font_cap_height cap_height#;
+font_asc_height asc_height#;
+%</!test&!t5supp&(rm|it|csc)>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*!test&!t5supp&(rm|it|csc)>
+font_acc_cap_height (cap_height#+acc_height#);
+font_desc_depth desc_depth#;
+font_max_height (max(asc_height#,body_height#, cap_height#+acc_height#));
+font_max_depth (max(desc_depth#,paren_depth#,the_ogonek_depth#));
+font_baselineskip max(1.2*designsize,body_height#+paren_depth#);
+% font_digit_width % set inside the digits file
+% font_cap_stem % set after the programme of the capital I
+%</!test&!t5supp&(rm|it|csc)>
+% \end{macrocode}
+%
+% \subsubsection{Roman}
+%
+% \begin{macrocode}
+%<*!test&!t5supp&rm>
+if monospace:
+ font_normal_space 9u#; % no stretching or shrinking
+ font_quad 18u#;
+ font_extra_space 9u#;
+ input vnmligtb; % ligature := monospaced fonts
+else:
+ font_normal_space 6u# + 2letter_fit#;
+ font_normal_stretch 3u#;
+ font_normal_shrink 2u#;
+ font_quad 18u# + 4letter_fit#;
+ font_extra_space 2u#;
+ input vnrligtb; % ligature := not monospaced fonts
+fi
+%</!test&!t5supp&rm>
+% \end{macrocode}
+%
+% \subsubsection{Italic}
+%
+% \begin{macrocode}
+%<*!test&!t5supp&it>
+if monospace:
+ font_normal_space 9u#; % no stretching or shrinking
+ font_quad 18u#;
+ font_extra_space 9u#;
+ letter_fit# := letter_fit
+ := 0;
+ input vnmligtb; % ligature := monospaced
+else:
+ font_normal_space 6u#+2letter_fit#;
+ font_normal_stretch 3u#;
+ font_normal_shrink 2u#;
+ font_quad 18u#+4letter_fit#;
+ font_extra_space 2u#;
+ input vniligtb; % ligature := proportionally spaced
+fi
+%</!test&!t5supp&it>
+% \end{macrocode}
+%
+% \subsubsection{CSC}
+%
+% \begin{macrocode}
+%<*!test&csc&!t5supp>
+if monospace:
+ font_normal_space 9u#; % no stretching or shrinking
+ font_quad 18u#;
+ font_extra_space 9u#;
+ input vnmligtb; % do the monospace ligature programs
+else:
+ font_normal_space 6u# + 2letter_fit#;
+ font_normal_stretch 3u#;
+ font_normal_shrink 2u#;
+ font_quad 18u# + 4letter_fit#;
+ font_extra_space 2u#;
+ input vncligtb; % do the ligature programs, not for monospaced fonts
+fi
+%</!test&csc&!t5supp>
+% \end{macrocode}
+%
+% \endinput
diff --git a/support/pydocstrip/vnparam.dtx b/support/pydocstrip/vnparam.dtx new file mode 100644 index 0000000000..8c0c93fc9e --- /dev/null +++ b/support/pydocstrip/vnparam.dtx @@ -0,0 +1,105 @@ +% \iffalse
+%<dtx>\ProvidesFile{vnparam.dtx}[2003/11/01 v02.02 VNR.KTV.DTX.Parameter]
+% \fi
+%
+% \section{Parameter Files}
+%
+% Tríc ngµy |2003/11/30|, c¸c |parameter| |file| ®îc thÓ hiÖn rÊt
+% r¾c rèi, vµ file |vnparam.dtx| dµi lª thª. B»ng c¸ch sö dông <<|kins|>>
+% file vµ <<|docstrip|>> ®Ó t¹o file |MF| tõ file |DTX|, mäi viÖc cã
+% vÎ ®¬n gi¶n h¬n nhiÒu. Bï l¹i, ph¶i khai b¸o c¸c |postamble| trong
+% <<|kins|>> file.
+%
+% \subsection{Generation Sizes}
+%
+% \begin{macrocode}
+gensize:=
+% \end{macrocode}
+%
+% \begin{multicols}4
+% \begin{macrocode}
+%<sz1|sz0100>1
+%<sz2|sz0200>2
+%<sz3|sz0300>3
+%<sz4|sz0400>4
+%<sz5|sz0500>5
+%<sz6|sz0600>6
+%<sz7|sz0700>7
+%<sz8|sz0800>8
+%<sz9|sz0900>9
+%<sz10|sz1000>10
+%<sz1095>10.95
+%<sz11|sz1100>11
+%<sz12|sz1200>12
+%<sz13|sz1300>13
+%<sz14|sz1400>14
+%<sz1440>14.40
+%<sz15|sz1500>15
+%<sz16|sz1600>16
+%<sz17|sz1700>17
+%<sz1728>17.28
+%<sz18|sz1800>18
+%<sz19|sz1900>19
+%<sz20|sz2000>20
+%<sz2074>20.74
+%<sz21|sz2100>21
+%<sz22|sz2200>22
+%<sz23|sz2300>23
+%<sz24|sz2400>24
+%<sz2488>24.88
+%<sz25|sz2500>25
+%<sz26|sz2600>26
+%<sz27|sz2700>27
+%<sz28|sz2800>28
+%<sz29|sz2900>29
+%<sz2986>29.86
+%<sz30|sz3000>30
+%<sz31|sz3100>31
+%<sz32|sz3200>32
+%<sz33|sz3300>33
+%<sz34|sz3400>34
+%<sz35|sz3500>35
+%<sz3583>35.83
+%<sz36|sz3600>36
+%<sz37|sz3700>37
+%<sz38|sz3800>38
+%<sz39|sz3900>39
+% \end{macrocode}
+% Chóng ta muèn xem ®iÒu kú diÖu...
+% \begin{macrocode}
+%<sz50|sz5000>50
+%<sz60|sz6000>60
+%<sz70|sz7000>70
+%<sz80|sz8000>80
+%<sz90|sz9000>90
+%<sz100|sz10000>100
+% \end{macrocode}
+% \end{multicols}
+%
+% \subsection{Common Hooks}
+%
+% \begin{macrocode}
+;input vnhook;
+hook_acc_wh(u.acute_,1.2,1.2);
+% \end{macrocode}
+%
+% \subsection{Private Hooks}
+%
+% \begin{macrocode}
+%<csc> hook_acc_wh(l.acute_,1.3,1.3);
+%<ff> hook_acc_wh(l.acute_,1.2,.6);
+%<ff> hook_acc_wh(u.acute_,1.2,.6);
+% \end{macrocode}
+%
+% \begin{macrocode}
+input vnbase;
+% \end{macrocode}
+%
+% \danger
+% ViÖc "load" c¸c "driver" cña font "ec" kh«ng xuÊt hiÖn ë ®©y...
+% bëi v× <<"docstrip">> sÏ thªm c¸c m· thÝch hîp
+% khi t¹o file "mf" tõ file "dtx".
+% Xem (ch¼ng h¹n) file \href{vnr_ec.kins}{vnr_ec.kins} ®Ó biÕt t¹i sao.
+% \endanger
+%
+% \endinput
diff --git a/support/pydocstrip/vnr.kins b/support/pydocstrip/vnr.kins new file mode 100644 index 0000000000..f3f248ac32 --- /dev/null +++ b/support/pydocstrip/vnr.kins @@ -0,0 +1,80 @@ +## VNR-METAFONT program +## Line start with a sharp (#) is the comment line + +$docstrip=1793 + +## require docstrip version 1793 or higher +## TRY: `docstrip --version` + +## default local variables + +## If these variables arenot specified from the command line +## they accept the default value given. + +$local(t5supp=0) +$local(test=1) +$local(nopre=1) +$local(cm=1) +$local(ec=0) +$local(param=1) + +## The following code arenot valuable +$local(destdir=tempdir) + +## default destination +$destdir=tempdir + +$if(t5supp=1) + $test=0 +$enif + +$import(vnr_pp) +## import file vnr_pp.kins + +$from(vnbase.dtx) +## the source file is vnbase.dtx + + $gen(vnbase.mf)(vnbase,test)(test=1) + $gen(vnbase.mf)(vnbase)(test=0,t5supp=0) + $gen(vnbase.mf)(vnbase,t5supp)(test=0,t5supp=1) + +$from(vndriver.dtx) +## the source file now is vndriver.dtx + + $if(test=1) + $gen(vncsc.mf)(csc,test) + $gen(vntextit.mf)(it,test) + $gen(vnroman.mf)(rm,test) + $else + $gen(vncsc.mf)(csc) + $gen(vnroman.mf)(rm) + $gen(vntextit.mf)(it) + $enif + + $if(t5supp=1) + $if(test=0) + $gen(vncsc.mf)(csc,t5supp) + $gen(vnroman.mf)(rm,t5supp) + $gen(vntextit.mf)(it,t5supp) + $enif + $enif + +######################################################################## + +$if(param=1) + $pre + %% This file is a part of VNR-METAFONT program. + $enpre + + $if(ec=1) + $import(vnr_ec) + $enif + + $if(cm=1) + $import(vnr_cm) + $enif +$enif + +$eof=1 + +######################################################################## diff --git a/support/pydocstrip/vnr_cm.kins b/support/pydocstrip/vnr_cm.kins new file mode 100644 index 0000000000..b13a0e586b --- /dev/null +++ b/support/pydocstrip/vnr_cm.kins @@ -0,0 +1,19 @@ +## VNR-METAFONT program
+
+## Parameter files -- names base on CMR font
+
+$docstrip=1792
+
+$if(cm=1)
+ $nopost=0
+ $from(vnparam.dtx)
+
+ $post=input ecbi;bye.\n
+ $gen(vnbxti7.mf)(bxti,sz7)
+ $gen(vnbxti8.mf)(bxti,sz8)
+
+ $post=input ecbx;bye.\n
+ $gen(vnbx5.mf)(bx,sz5)
+$enif
+
+$eof=1
diff --git a/support/pydocstrip/vnr_ec.kins b/support/pydocstrip/vnr_ec.kins new file mode 100644 index 0000000000..ed6800a06f --- /dev/null +++ b/support/pydocstrip/vnr_ec.kins @@ -0,0 +1,17 @@ +## VNR-METAFONT program
+
+## Parameter files -- names base on EC font
+
+$docstrip=1792
+
+$if(ec=1)
+ $nopost=0
+ $from(vnparam.dtx)
+
+ $post=input ecbi;bye.\n
+ $gen(vnbi0500.mf)(sz0500)
+ $gen(vnbi0600.mf)(sz0600)
+ $post=input
+$enif
+
+$eof=1
diff --git a/support/pydocstrip/vnr_pp.kins b/support/pydocstrip/vnr_pp.kins new file mode 100644 index 0000000000..bb98a49e68 --- /dev/null +++ b/support/pydocstrip/vnr_pp.kins @@ -0,0 +1,40 @@ +## VNR-METAFONT program + +## Default Preamble, Postamble + +$if(nopre=0) + $pre + %% + %% This is file `$dest' which was generated from + %% the source `$source' + %% with option `$option'. + %% + %% The generator was `$generator' + %% and the generation date was `$date'. + %% + %% This is a test preamble. In the preabmle + %% you have five expandanable macros: + %% + %% ${c} : the sharp ($c) + %% ${dest} : the destination + %% ${source} : the source file + %% ${option} : list of options used + %% ${generator} : print information about the generator + %% ${date} : print the generation date + %% + %% Please see the usage in the file `vnr_pp.kins'. + $c$c + $c$c This line will start with two sharp + $c$c + %% + $enpre +$enif + +$if(nopost=0) + $post + endinput; + %% End of file `$dest'. + $enpost +$enif + +$eof=1 |