1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %%% WEB Change File for PUTeX (CJK version)
4 %%% Modified and patched version for TeX Live
6 %%% Copyright (C) 1997-2004 Chey-Woei Tsay <cwtsay@pu.edu.tw>
7 %%% Copyright (C) 2013-2014 Clerk Ma <clerkma@gmail.com>
9 %%% This is the change file of PUTeX.
11 %%% PUTeX is a free software; you can redistribute it and/or
12 %%% modify it under the terms of the GNU General Public License as
13 %%% published by the Free Software Foundation; either version 3, or (at
14 %%% your option) any later version.
16 %%% PUTeX is distributed in the hope that it will be useful, but
17 %%% WITHOUT ANY WARRANTY; without even the implied warranty of
18 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 %%% General Public License for more details.
21 %%% You should have received a copy of the GNU General Public License
22 %%% along with TeX Live; if not, write to the Free Software
23 %%% Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 %%% add \PUXcatcode command to set catcodes of dbcs characters.
29 %%% remove print_dbchar (58, 59, 70, 318, print_chinese_int)
32 %%% removed the MikTeX part.
36 %%% new_character(582), make_accent(1123), char_box, rebox
37 %%% mathmode: be awear of print_ASCII
38 %%% check '(cat_code(buffer[loc])<>escape)' in section 1337
40 %%% \PUXsetcfacehook -- set cface hook macro that is called when switched to the cface
41 %%% \PUXsetcfonthook -- set cfont hook macro that is called when switched to the cfont
43 %%% see section 224 for cspace skip and cespace skip
46 %%% @^Input Encoding Dependencies@>
47 %%% @^Modified for handling DBCS characters@>
48 %%% @^CJK Fonts Extension@>
51 \def\gglob{20, 26} % this should be the next two sections of "<Global...>"
53 \def\gglob{20, 26} % this should be the next two sections of "<Global...>"
55 \def\putexadd{\hskip -0.5in putex -- add -- }
56 \def\putexmod{\hskip -0.5in putex -- mod -- }
57 \def\putexend{\hskip -0.5in putex -- end -- }
62 @d banner_k==TeX_banner_k
64 @d PUTeX_version_string=='-5.0' {current \PUTeX\ version}
66 @d PUTeX_banner=='This is PUTeX, Version 3.1415926',PUTeX_version_string
67 @d PUTeX_banner_k==PUTeX_banner
68 {printed when \PUTeX\ starts}
70 @d banner==PUTeX_banner
71 @d banner_k==PUTeX_banner_k
75 @t\4@>@<Error handling procedures@>@/
77 @t\4@>@<Error handling procedures@>@/
78 @t\4@>@<PUTeX routines that will be used by TeX routines@>@/
87 for k := 0 to 255 do xchr[k] := k;
93 The |append_char| macro, defined here, does not check to see if the
94 value of |pool_ptr| has gotten too high; this test is supposed to be
95 made before |append_char| is used. There is also a |flush_char|
97 The |append_char| and |append_wchar| macros, defined here, do not check to see if the
98 value of |pool_ptr| has gotten too high; this test is supposed to be
99 made before |append_char| (or |append_wchar|) is used. There is also a |flush_char|
103 @d append_char(#) == {put |ASCII_code| \# at the end of |str_pool|}
104 begin str_pool[pool_ptr]:=si(#); incr(pool_ptr);
107 @d append_char(#) == {put |ASCII_code| \# at the end of |str_pool|}
108 begin str_pool[pool_ptr]:=si(#); incr(pool_ptr);
111 @d append_wchar(#) == {TCW: put a double-byte char \# at the end of |str_pool|}
112 begin str_pool[pool_ptr]:=# div 256; str_pool[pool_ptr+1]:=# mod 256;
113 pool_ptr:=pool_ptr+2;
119 using the |xchr| array to map it into an external character compatible with
120 |input_ln|. All printing comes through |print_ln| or |print_char|.
122 using the |xchr| array to map it into an external character compatible with
123 |input_ln|. All printing comes through |print_ln|, |print_char|, or |print_wchar|.
125 TCW: The |print_wchar| macro is used to print one DBCS character.
127 @d print_wchar(#)==begin print_char((#) div 256); print_char((#) mod 256) end {TCW}
131 @d character == subtype {the character code in a |char_node|}
133 @d character == subtype {the character code in a |char_node|}
134 @d is_wchar_node(#) == (character(#)>255)
135 @d is_wchar(#) == ((#)>255)
138 %% parallel kanji font, when typesetting kanjis, we need a match table.
140 @!font_in_short_display:integer; {an internal font number}
142 @!font_in_short_display:integer; {an internal font number}
143 @!cfont_in_short_display:integer; {TCW: an internal CJK font number}
147 sort of ``complicated'' are indicated only by printing `\.{[]}'.
149 sort of ``complicated'' are indicated only by printing `\.{[]}'.@^CJK Fonts Extension@>
153 begin if font(p)<>font_in_short_display then
154 begin if (font(p)>font_max) then
157 else @<Print the font identifier for |font(p)|@>;
158 print_char(" "); font_in_short_display:=font(p);
160 print_ASCII(qo(character(p)));
163 begin if font(p)<>font_in_short_display and font(p)<>cfont_in_short_display then
164 begin if (font(p)>cfont_max) then
167 else @<Print the font identifier for |font(p)|@>;
169 if font(p) <= font_max then
170 font_in_short_display:=font(p)
172 cfont_in_short_display:=font(p);
174 if is_wchar_node(p) then
175 print_wchar(character(p))
177 print_ASCII(qo(character(p)));
182 its reference count, and one to print a rule dimension.
184 its reference count, and one to print a rule dimension.@^CJK Fonts Extension@>
188 else begin if (font(p)>font_max) then print_char("*")
190 else begin if (font(p)>cfont_max) then print_char("*")
194 print_char(" "); print_ASCII(qo(character(p)));
197 if is_wchar_node(p) then
198 print_wchar(character(p))
200 print_ASCII(qo(character(p)));
205 @d max_char_code=15 {largest catcode for individual characters}
207 @d max_char_code=15 {largest catcode for individual characters}
208 @d boundary_normal=0 {CJK characters can be in any positions of lines}
209 @d tail_forbidden=1 {CJK characters can't be put in the head of lines}
210 @d head_forbidden=2 {CJK characters can't be put in the tail of lines}
211 @d max_type_code=2 {largest boundary code for CJK characters}
212 @d set_type_code_end(#) == # end
213 @d set_type_code(#) == begin
214 type_code(#) := set_type_code_end
218 @ The next codes are special; they all relate to mode-independent
219 assignment of values to \TeX's internal registers or tables.
220 Codes that are |max_internal| or less represent internal quantities
221 that might be expanded by `\.{\\the}'.
223 @ The next codes are special; they all relate to mode-independent
224 assignment of values to \TeX's internal registers or tables.
225 Codes that are |max_internal| or less represent internal quantities
226 that might be expanded by `\.{\\the}'.
228 TCW: Add 3 internal commands: |set_cfont|, |puxg_assign_flag|, and |puxg_assign_int|.
229 Add 12 user commands: |pux_cface_def|, |pux_face_match|, |pux_font_match|,
230 |pux_set_cface|, |pux_set_cface_attrib|,|pux_set_cfont_attrib|,
231 |pux_char_num|, |pux_char_given|, |pux_space|, |pux_range_catcode|,
232 |pux_range_type_code|, and |pux_dump_font_info|.@^CJK Fonts Extension@>
236 @d def_font=88 {define a font file ( \.{\\font} )}
237 @d register=89 {internal register ( \.{\\count}, \.{\\dimen}, etc.~)}
238 @d max_internal=89 {the largest code that can follow \.{\\the}}
239 @d advance=90 {advance a register or parameter ( \.{\\advance} )}
240 @d multiply=91 {multiply a register or parameter ( \.{\\multiply} )}
241 @d divide=92 {divide a register or parameter ( \.{\\divide} )}
242 @d prefix=93 {qualify a definition ( \.{\\global}, \.{\\long}, \.{\\outer} )}
243 @d let=94 {assign a command code ( \.{\\let}, \.{\\futurelet} )}
244 @d shorthand_def=95 {code definition ( \.{\\chardef}, \.{\\countdef}, etc.~)}
245 {or \.{\\charsubdef}}
246 @d read_to_cs=96 {read into a control sequence ( \.{\\read} )}
247 @d def=97 {macro definition ( \.{\\def}, \.{\\gdef}, \.{\\xdef}, \.{\\edef} )}
248 @d set_box=98 {set a box ( \.{\\setbox} )}
249 @d hyph_data=99 {hyphenation data ( \.{\\hyphenation}, \.{\\patterns} )}
250 @d set_interaction=100 {define level of interaction ( \.{\\batchmode}, etc.~)}
251 @d max_command=100 {the largest command code seen at |big_switch|}
253 @d set_cfont=88 {TCW: set current chinese font ( font identifiers )}
254 @d def_font=89 {define a font file ( \.{\\font} )}
255 @d register=90 {internal register ( \.{\\count}, \.{\\dimen}, etc.~)}
256 @d puxg_assign_flag=91 {TCW: set a PU\TeX\ global flag (\.{\\puxgCdiOut}, \.{\\puxgRotateCtext})}
257 @d puxg_assign_int=92 {TCW: set a PU\TeX\ global integer (\.{\\puxgCspace}, \.{\\puxgCEspace})}
258 @d pux_get_int=93 {TCW: get internal integer values ( \.{\\PUXnumdigits}, \.{\\PUXsign}, \.{\\PUXdigit} )}
259 @d max_internal=93 {the largest code that can follow \.{\\the}}
260 @d advance=94 {advance a register or parameter ( \.{\\advance} )}
261 @d multiply=95 {multiply a register or parameter ( \.{\\multiply} )}
262 @d divide=96 {divide a register or parameter ( \.{\\divide} )}
263 @d prefix=97 {qualify a definition ( \.{\\global}, \.{\\long}, \.{\\outer} )}
264 @d let=98 {assign a command code ( \.{\\let}, \.{\\futurelet} )}
265 @d shorthand_def=99 {code definition ( \.{\\chardef}, \.{\\countdef}, etc.~)}
266 {or \.{\\charsubdef}}
267 @d read_to_cs=100 {read into a control sequence ( \.{\\read} )}
268 @d def=101 {macro definition ( \.{\\def}, \.{\\gdef}, \.{\\xdef}, \.{\\edef} )}
269 @d set_box=102 {set a box ( \.{\\setbox} )}
270 @d hyph_data=103 {hyphenation data ( \.{\\hyphenation}, \.{\\patterns} )}
271 @d set_interaction=104 {define level of interaction ( \.{\\batchmode}, etc.~)}
272 @d pux_cface_def=105 {TCW: define a chinese font face ( \.{\\PUXcfacedef} )}
273 @d pux_face_match=106 {TCW: English and Chinese face matching pair ( \.{\\PUXfacematch} )}
274 @d pux_font_match=107 {TCW: English and CJK font matching pair ( \.{\\PUXfontmatch} )}
275 @d pux_set_cface=108 {TCW: Set Chinese face}
276 @d pux_set_cface_attrib=109 {TCW: Set attributes of a Chinese face ( \.{\\PUXsetcfacecspace, etc.} )}
277 @d pux_set_cfont_attrib=110 {TCW: Set attributes of a CJK font ( \.{\\PUXsetcfontcspace, etc.} )}
278 @d pux_char_num=111 {TCW: Chinese character number ( \.{\\PUXchar} )}
279 @d pux_char_given=112 {TCW: define a Chinese character ( \.{\\PUXchardef} )}
280 @d pux_space=113 {Append space glue between Chinese and Tex characters ( \.{\\PUXcespace} )}
281 @d pux_range_catcode=114 {TCW: set catcodes for a range of characters( \.{\\PUXrangecatcode} )}
282 @d pux_range_type_code=115 {TCW: set catcodes for a range of characters( \.{\\PUXrangecatcode} )}
283 @d pux_split_number=116 {TCW: split a number to digits ( \.{\\PUXsplitnumber} )}
284 @d puxg_assign_space=117 {TCW: set a PU\TeX\ global integer (\.{\\puxgCspace}, \.{\\puxgCEspace})}
285 @d pux_set_default_cface=118 {TCW: set default CJK font face ( \.{\\PUXsetdefaultcface} )}
286 @d pux_dump_font_info=119 {TCW: dump font information ( \.{\\PUXdumpfontinfo} )}
287 @d max_command=119 {the largest command code seen at |big_switch|}
291 In the first region we have 256 equivalents for ``active characters'' that
292 act as control sequences, followed by 256 equivalents for single-character
295 In the first region we have 65536 equivalents for ``active characters'' that
296 act as control sequences, followed by 65536 equivalents for single-character
301 @d single_base=active_base+256 {equivalents of one-character control sequences}
302 @d null_cs=single_base+256 {equivalent of \.{\\csname\\endcsname}}
304 @d single_base=active_base+65536 {equivalents of one-character control sequences}
305 @d null_cs=single_base+65536 {equivalent of \.{\\csname\\endcsname}}
310 @d font_id_base=frozen_null_font-font_base
311 {begins table of 257 permanent font identifiers}
312 @d undefined_control_sequence=frozen_null_font+max_font_max+1 {dummy location}
314 @d font_id_base=frozen_null_font-font_base
315 {begins table of 257 permanent English font identifiers}
316 @d font_max_limit=5000
317 @d cfont_id_base=font_id_base+font_max_limit+1
318 {TCW: begins table of 'font\_max\_limit' permanent CJK font identifiers}
319 @d cfont_max_limit=font_max_limit
320 @d cface_id_base=cfont_id_base+cfont_max_limit+1
321 {TCW: begins table of 257 permanent Chinese face identifiers}
322 @d undefined_control_sequence=cface_id_base+257 {dummy location}
326 token parameters, as well as the tables of \.{\\toks} and \.{\\box}
329 token parameters, as well as the tables of \.{\\toks} and \.{\\box}
332 TCW: Define |cur_cfont_loc| for two-byte char and the macro |cur_cfont|.
336 @d math_font_base=cur_font_loc+1 {table of 48 math font numbers}
338 @d cur_cface_loc=cur_font_loc+1 {TCW: internal chinese font number outside math mode}
339 @d cur_cfont_loc=cur_cface_loc+1 {TCW: internal chinese font number outside math mode}
340 @d ectbl_cface_num_base=cur_cfont_loc+1 {TCW: table of 257 CJK face numbers matched with TeX face}
341 @d max_cface=256 {maximal CJK font faces number}
342 @d font_matching_table_base=ectbl_cface_num_base+max_cface+1 {table of font matches}
343 @d math_font_base=font_matching_table_base+font_max_limit+1 {table of 48 math font numbers}
347 {table of 256 command codes (the ``catcodes'')}
348 @d lc_code_base=cat_code_base+256 {table of 256 lowercase mappings}
350 {TCW: table of 65536 command codes (the ``catcodes'')}
351 @d pux_cat_code_base=cat_code_base+256
352 @d pux_type_code_base=cat_code_base+65536 {TCW: table of 65536 type codes}
353 @d lc_code_base=pux_type_code_base+65536 {table of 256 lowercase mappings}
357 @d math_code_base=sf_code_base+256 {table of 256 math mode mappings}
359 @d pux_local_names_base=sf_code_base+256 {TCW: table of 256 CJK name mappings.}
360 @d math_code_base=pux_local_names_base+256 {table of 256 math mode mappings}
364 @d cur_font==equiv(cur_font_loc)
366 @d cur_font==equiv(cur_font_loc)
367 @d cur_cface==equiv(cur_cface_loc) {TCW}
368 @d cur_cfont==equiv(cur_cfont_loc) {TCW}
369 @d ectbl_cface_num(#)==equiv(ectbl_cface_num_base+(#)) {TCW}
370 @d font_matching_table(#)==equiv(font_matching_table_base+((#)-font_base)) {TCW}
374 @d cat_code(#)==equiv(cat_code_base+#)
376 @d cat_code(#)==equiv(cat_code_base+#)
377 @d type_code(#)==equiv(pux_type_code_base+#)
378 @d local_names(#)==equiv(pux_local_names_base+#)
382 packages, not in \TeX\ itself, so that global interchange of formats is
385 packages, not in \TeX\ itself, so that global interchange of formats is
388 TCW: Add |null_cfont| and initialization for |cur_font|.
392 @d null_font==font_base
394 @d null_font==font_base
395 @d null_cfont==cfont_base
396 @d default_cfont==null_cfont+1
400 begin if n=cur_font_loc then print("current font")
401 else if n<math_font_base+16 then
403 begin if n=cur_font_loc then print("current font")
404 else if n=cur_cface_loc then print("current cface")
405 else if n=cur_cfont_loc then print("current cfont")
406 else if n<math_font_base+16 then
410 begin if n<lc_code_base then
411 begin print_esc("catcode"); print_int(n-cat_code_base);
414 begin if n<pux_type_code_base then
416 if n<pux_cat_code_base then print_esc("catcode")
417 else print_esc("PUXcatcode");
418 print_int(n-cat_code_base);
420 else if n<lc_code_base then
421 begin print_esc("PUXtypecode"); print_int(n-pux_type_code_base);
426 else begin print_esc("sfcode"); print_int(n-sf_code_base);
429 else if n<pux_local_names_base then
430 begin print_esc("sfcode"); print_int(n-sf_code_base);
432 else begin print_esc("PUXlocalnames"); print_int(n-pux_local_names_base);
437 print_char("="); print_int(equiv(n));
440 if n>=pux_local_names_base then
441 if n < 256 then print_char(equiv(n))
442 else print_wchar(equiv(n))
443 else print_int(equiv(n));
447 @d error_context_lines_code=54 {maximum intermediate line pairs shown}
448 @d tex_int_pars=55 {total number of \TeX's integer parameters}
450 @d error_context_lines_code=54 {maximum intermediate line pairs shown}
451 @d puxg_rotate_ctext_code=55
452 @d puxg_cface_depth_code=56
453 @d pux_xspace_code=57
454 @d pux_wcharother_code=58
455 @d pux_CJKinput_code=59
456 @d pux_charset_code=60
457 @d pux_default_cface_code=61
458 @d pux_digit_num_code=62 {number of digits of the splitted number}
459 @d pux_sign_code=63 {sign of the splitted number}
460 @d pux_digit_base=64 {10 digits of splitted number}
461 @d tex_int_pars=74 {total number of \TeX's integer parameters}
465 @d error_context_lines==int_par(error_context_lines_code)
467 @d error_context_lines==int_par(error_context_lines_code)
468 @d puxg_rotate_ctext==int_par(puxg_rotate_ctext_code)
469 @d puxg_cface_depth==int_par(puxg_cface_depth_code)
470 @d pux_xspace==int_par(pux_xspace_code)
471 @d pux_wcharother==int_par(pux_wcharother_code)
472 @d pux_CJKinput==int_par(pux_CJKinput_code)
473 @d pux_charset==int_par(pux_charset_code)
474 @d pux_default_cface==int_par(pux_default_cface_code)
475 @d pux_digit_num==int_par(pux_digit_num_code)
476 @d pux_num_sign==int_par(pux_sign_code)
477 @d pux_nth_digit(#)==int_par(pux_digit_base+#)
484 othercases print("[unknown integer parameter!]")
486 pux_xspace_code:print_esc("puxXspace");
487 pux_wcharother_code:print_esc("puxCJKcharOther");
488 pux_CJKinput_code:print_esc("puxCJKinput");
489 pux_charset_code:print_esc("puxCharSet");
490 puxg_rotate_ctext_code:print_esc("puxgRotateCtext");
491 puxg_cface_depth_code:print_esc("puxgCfaceDepth");
492 othercases print("[unknown integer parameter!]")
496 del_code("."):=0; {this null delimiter is used in error recovery}
498 del_code("."):=0; {this null delimiter is used in error recovery}
499 puxg_cface_depth:=default_depth;
504 if cat_code(p-single_base)=letter then print_char(" ");
506 if get_cat_code(p-single_base)=letter then print_char(" ");
510 def_font: print_esc("font");
512 def_font: print_esc("font");
513 pux_font_match: print_esc("PUXfontmatch"); {TCW}
514 pux_set_cface: print_esc("cface"); {TCW}
515 pux_range_catcode: print_esc("PUXrangecatcode"); {TCW}
516 pux_range_type_code: print_esc("PUXrangetypecode"); {TCW}
517 pux_split_number: print_esc("PUXsplitnumber"); {TCW}
521 A \TeX\ token is either a character or a control sequence, and it is
523 represented internally in one of two ways: (1)~A character whose ASCII
524 code number is |c| and whose command code is |m| is represented as the
525 number $2^8m+c$; the command code is in the range |1<=m<=14|. (2)~A control
526 sequence whose |eqtb| address is |p| is represented as the number
527 |cs_token_flag+p|. Here |cs_token_flag=@t$2^{12}-1$@>| is larger than
528 $2^8m+c$, yet it is small enough that |cs_token_flag+p< max_halfword|;
529 thus, a token fits comfortably in a halfword.
531 A token |t| represents a |left_brace| command if and only if
532 |t<left_brace_limit|; it represents a |right_brace| command if and only if
533 we have |left_brace_limit<=t<right_brace_limit|; and it represents a |match| or
534 |end_match| command if and only if |match_token<=t<=end_match_token|.
535 The following definitions take care of these token-oriented constants
538 @d cs_token_flag==@'7777 {amount added to the |eqtb| location in a
539 token that stands for a control sequence; is a multiple of~256, less~1}
540 @d left_brace_token=@'0400 {$2^8\cdot|left_brace|$}
541 @d left_brace_limit=@'1000 {$2^8\cdot(|left_brace|+1)$}
542 @d right_brace_token=@'1000 {$2^8\cdot|right_brace|$}
543 @d right_brace_limit=@'1400 {$2^8\cdot(|right_brace|+1)$}
544 @d math_shift_token=@'1400 {$2^8\cdot|math_shift|$}
545 @d tab_token=@'2000 {$2^8\cdot|tab_mark|$}
546 @d out_param_token=@'2400 {$2^8\cdot|out_param|$}
547 @d space_token=@'5040 {$2^8\cdot|spacer|+|" "|$}
548 @d letter_token=@'5400 {$2^8\cdot|letter|$}
549 @d other_token=@'6000 {$2^8\cdot|other_char|$}
550 @d match_token=@'6400 {$2^8\cdot|match|$}
551 @d end_match_token=@'7000 {$2^8\cdot|end_match|$}
553 A \TeX\ token is either a character or a control sequence, and it is
555 represented internally in one of two ways: (1)~A character whose ASCII
556 code number is |c| and whose command code is |m| is represented as the
557 number $2^{16}m+c$; the command code is in the range |1<=m<=14|. (2)~A control
558 sequence whose |eqtb| address is |p| is represented as the number
559 |cs_token_flag+p|. Here |cs_token_flag=@t$2^{20}-1$@>| is larger than
560 $2^{16}m+c$, yet it is small enough that |cs_token_flag+p< max_halfword|;
561 thus, a token fits comfortably in a halfword.
563 A token |t| represents a |left_brace| command if and only if
564 |t<left_brace_limit|; it represents a |right_brace| command if and only if
565 we have |left_brace_limit<=t<right_brace_limit|; and it represents a |match| or
566 |end_match| command if and only if |match_token<=t<=end_match_token|.
567 The following definitions take care of these token-oriented constants
570 @d cs_token_flag==@"FFFFF {amount added to the |eqtb| location in a
571 token that stands for a control sequence; is a multiple of~65536, less~1}
572 @d left_brace_token==@"10000 {$2^{16}\cdot|left_brace|$}
573 @d left_brace_limit==@"20000 {$2^{16}\cdot(|left_brace|+1)$}
574 @d right_brace_token==@"20000 {$2^{16}\cdot|right_brace|$}
575 @d right_brace_limit==@"30000 {$2^{16}\cdot(|right_brace|+1)$}
576 @d math_shift_token==@"30000 {$2^{16}\cdot|math_shift|$}
577 @d tab_token==@"40000 {$2^{16}\cdot|tab_mark|$}
578 @d out_param_token==@"50000 {$2^{16}\cdot|out_param|$}
579 @d space_token==@"A0020 {$2^{16}\cdot|spacer|+|" "|$}
580 @d letter_token==@"B0000 {$2^{16}\cdot|letter|$}
581 @d other_token==@"C0000 {$2^{16}\cdot|other_char|$}
582 @d match_token==@"D0000 {$2^{16}\cdot|match|$}
583 @d end_match_token==@"E0000 {$2^{16}\cdot|end_match|$}
587 else begin m:=info(p) div @'400; c:=info(p) mod @'400;
589 else begin m:=info(p) div @"10000; c:=info(p) mod @"10000;
593 left_brace,right_brace,math_shift,tab_mark,sup_mark,sub_mark,spacer,
594 letter,other_char: print(c);
596 letter,other_char: if is_wchar(c) then print_wchar(c) else print(c);
597 left_brace,right_brace,math_shift,tab_mark,sup_mark,sub_mark,spacer: print(c);
601 @d chr_cmd(#)==begin print(#); print_ASCII(chr_code);
604 @d chr_cmd(#)==begin print(#); print_ASCII(chr_code);
606 @d wchr_cmd(#)==begin print(#);
607 if is_wchar(chr_code) then
608 print_wchar(chr_code)
609 else print_ASCII(chr_code);
614 letter: chr_cmd("the letter ");
615 other_char: chr_cmd("the character ");
617 letter: wchr_cmd("the letter ");
618 other_char: wchr_cmd("the character ");
622 @!d:2..3; {number of excess characters in an expanded code}
624 @!d:2..3; {number of excess characters in an expanded code}
625 @!first_control_char:integer; {the first character code of control sequence}
629 @ @<Input from external file, |goto restart| if no input found@>=
631 begin switch: if loc<=limit then {current line not yet finished}
632 begin cur_chr:=buffer[loc]; incr(loc);
634 @ The |get_wchar| macro tries to read a double-byte character from |buffer|
635 at the position specified by the parameter. The code value is stored in the
636 global variable |cur_chr|.
638 @^Modified for handling DBCS characters@>
640 @d get_wchar(#)==begin cur_chr:=buffer[#]; incr(#);
641 if cur_chr > 127 and pux_CJKinput = 1 then begin
642 cur_chr := cur_chr * 256 + buffer[#]; incr(#)
646 @<Input from external file, |goto restart| if no input found@>=
647 begin switch: if loc<=limit then {current line not yet finished}
648 begin get_wchar(loc);
652 reswitch: cur_cmd:=cat_code(cur_chr);
654 reswitch: cur_cmd:=get_cat_code(cur_chr);
658 buffer and the process is repeated, slowly but surely.
660 @<Scan a control...@>=
661 begin if loc>limit then cur_cs:=null_cs {|state| is irrelevant in this case}
662 else begin start_cs: k:=loc; cur_chr:=buffer[k]; cat:=cat_code(cur_chr);
665 buffer and the process is repeated, slowly but surely.
669 TCW: When the flag |expand_char| is true, we stop using |get_wchar| but
670 merely get a one-byte character so that reading DBCS characters
671 will not be confused. Besides, we neet to handle alphabetic numbers of the form
672 \.{'\\c}, where \.{c} is a DBCS characters.@^Modified for handling DBCS characters@>
674 @<Scan a control...@>=
675 begin if loc>limit then cur_cs:=null_cs {|state| is irrelevant in this case}
676 else begin first_control_char := -1;@/
678 if expand_char then begin
684 cat:=get_cat_code(cur_chr);
685 if first_control_char = -1 then first_control_char := cur_chr;
689 cur_cs:=single_base+buffer[loc]; incr(loc);
692 @#{the control sequence is a control symbol, i.e., its name consisits of only one letter. }
693 if is_wchar(first_control_char) then begin
694 cur_cs:=single_base+first_control_char; loc:=loc+2;
697 cur_cs:=single_base+buffer[loc]; incr(loc);
703 the buffer left two or three places.
705 the buffer left two or three places.
707 TCW: If it is indeed an expanded code, set the flag |expand_char|.
708 @^Modified for handling DBCS characters@>
712 begin c:=buffer[k+1]; @+if c<@'200 then {yes, one is indeed present}
715 begin c:=buffer[k+1]; @+if c<@'200 then {yes, one is indeed present}
716 begin d:=2; expand_char:=true;
720 @ @<Scan ahead in the buffer...@>=
721 begin repeat cur_chr:=buffer[k]; cat:=cat_code(cur_chr); incr(k);
723 @ @<Scan ahead in the buffer...@>=
724 @^Modified for handling DBCS characters@>
725 begin repeat get_wchar(k); cat:=get_cat_code(cur_chr);
729 if cat<>letter then decr(k);
730 {now |k| points to first nonletter}
731 if k>loc+1 then {multiletter control sequence has been scanned}
733 if cat<>letter then if cur_chr > 256 then k:=k-2 { go back 2 steps for a non-letter DBCS code }
735 {now |k| points to first nonletter}
736 if k>loc+1 and not (k = loc+2 and first_control_char > 255) then {multiletter control sequence has been scanned}
740 else begin cur_cmd:=t div @'400; cur_chr:=t mod @'400;
742 else begin cur_cmd:=t div @"10000; cur_chr:=t mod @"10000;
746 if cur_cs=0 then cur_tok:=(cur_cmd*@'400)+cur_chr
748 if cur_cs=0 then cur_tok:=(cur_cmd*@"10000)+cur_chr
752 buffer[j]:=info(p) mod @'400; incr(j); p:=link(p);
754 @^Modified for handling DBCS characters@>
755 db_char:=info(p) mod @"10000;
756 if is_wchar(db_char) then {a double-byte char}
757 begin buffer[j]:=db_char div 256;
758 buffer[j+1]:=db_char mod 256;
765 p:=link(p); {fix this for 2-byte code}
769 done: if cur_cs=0 then cur_tok:=(cur_cmd*@'400)+cur_chr
771 done: if cur_cs=0 then cur_tok:=(cur_cmd*@"10000)+cur_chr
775 if cur_cs=0 then cur_tok:=(cur_cmd*@'400)+cur_chr
777 if cur_cs=0 then cur_tok:=(cur_cmd*@"10000)+cur_chr
781 toks_register,assign_toks,def_family,set_font,def_font: @<Fetch a token list or
782 font identifier, provided that |level=tok_val|@>;
784 toks_register,assign_toks,def_family,set_font,def_font,set_cfont:
785 @<Fetch a token list or font identifier, provided that |level=tok_val|@>;
789 assign_int: scanned_result(eqtb[m].int)(int_val);
791 assign_int,puxg_assign_flag,puxg_assign_int: scanned_result(eqtb[m].int)(int_val);
792 pux_get_int:@<scan \PUTeX\ internal values@>;
796 char_given,math_given: scanned_result(cur_chr)(int_val);
798 char_given,math_given,pux_char_given: scanned_result(cur_chr)(int_val);
802 @ @<Fetch a character code from some table@>=
805 @ @<Fetch a character code from some table@>=
807 if (m = pux_cat_code_base) or (m = pux_type_code_base) then
809 else if m = pux_local_names_base then begin
818 begin scan_font_ident;
819 if m=0 then scanned_result(hyphen_char[cur_val])(int_val)
820 else scanned_result(skew_char[cur_val])(int_val);
823 begin scan_font_ident;
824 if cur_val <= font_max then
825 if m=0 then scanned_result(hyphen_char[cur_val])(int_val)
826 else scanned_result(skew_char[cur_val])(int_val);
831 @d octal_token=other_token+"'" {apostrophe, indicates an octal constant}
832 @d hex_token=other_token+"""" {double quote, indicates a hex constant}
833 @d alpha_token=other_token+"`" {reverse apostrophe, precedes alpha constants}
834 @d point_token=other_token+"." {decimal point}
835 @d continental_point_token=other_token+"," {decimal point, Eurostyle}
837 @d octal_token==(other_token+"'") {apostrophe, indicates an octal constant}
838 @d hex_token==(other_token+"""") {double quote, indicates a hex constant}
839 @d alpha_token==(other_token+"`") {reverse apostrophe, precedes alpha constants}
840 @d point_token==(other_token+".") {decimal point}
841 @d continental_point_token==(other_token+",") {decimal point, Eurostyle}
847 if cur_val>65535 then
851 @d zero_token=other_token+"0" {zero, the smallest digit}
852 @d A_token=letter_token+"A" {the smallest special hex digit}
853 @d other_A_token=other_token+"A" {special hex digit of type |other_char|}
855 @d zero_token==(other_token+"0") {zero, the smallest digit}
856 @d A_token==(letter_token+"A") {the smallest special hex digit}
857 @d other_A_token==(other_token+"A") {special hex digit of type |other_char|}
861 `\.{height}' or `\.{width}' or `\.{depth}' specifications are
862 found (in any order).
864 `\.{height}' or `\.{width}' or `\.{depth}' specifications are
865 found (in any order).
867 TCW: not intend to modify the function here;
868 just append declarations of scanning routines for PUTeX.
872 if scan_keyword("depth") then
874 begin scan_normal_dimen; depth(q):=cur_val; goto reswitch;
879 if scan_keyword("depth") then
881 begin scan_normal_dimen; depth(q):=cur_val; goto reswitch;
886 @<PUTeX basic scanning routines@>@;
890 var p:pointer; {tail of the token list}
891 @!q:pointer; {new node being added to the token list via |store_new_token|}
892 @!t:halfword; {token being appended}
893 @!k:pool_pointer; {index into |str_pool|}
895 p:=temp_head; link(p):=null; k:=b;
897 begin t:=so(str_pool[k]);
898 if t=" " then t:=space_token
899 else t:=other_token+t;
900 fast_store_new_token(t);
903 pool_ptr:=b; str_toks:=p;
906 var p:pointer; {tail of the token list}
907 @!q:pointer; {new node being added to the token list via |store_new_token|}
908 @!t:halfword; {token being appended}
909 @!k:pool_pointer; {index into |str_pool|}
911 p:=temp_head; link(p):=null; k:=b;
913 begin t:=so(str_pool[k]);
914 if t > 128 then begin
915 t:=t*256+so(str_pool[k+1]);
918 if t=" " then t:=space_token
919 else t:=other_token+t;
920 fast_store_new_token(t);
923 pool_ptr:=b; str_toks:=p;
928 containing something like `\.{-3.0pt minus 0.5fill}'.
930 containing something like `\.{-3.0pt minus 0.5fill}'.
932 TCW: make the function able to print CJK characters stored in local names table.
937 begin get_x_token; scan_something_internal(tok_val,false);
939 begin get_x_token; char_val_flag:=false; scan_something_internal(tok_val,false);
943 int_val:print_int(cur_val);
945 int_val:if char_val_flag then
946 if cur_val > 255 then print_wchar(cur_val)
948 begin print_char("?"); print_char("?"); end
949 else print_int(cur_val);
953 @d font_name_code=4 {command code for \.{\\fontname}}
954 @d job_name_code=5 {command code for \.{\\jobname}}
956 @d font_name_code=4 {command code for \.{\\fontname}}
957 @d cnumber_code=5 {command code for \.{\\PUXcnumber}}
958 @d scnumber_code=6 {command code for \.{\\PUXscnumber}}
959 @d ucnumber_code=7 {command code for \.{\\PUXucnumber}}
960 @d fcnumber_code=8 {command code for \.{\\PUXfcnumber}}
961 @d acnumber_code=9 {command code for \.{\\PUXacnumber}}
962 @d cjknumber_code=10 {command code for \.{\\PUXcjknumber}}
963 @d nameseq_code=11 {command code for \.{\\PUXnameseq}}
964 @d job_name_code=12 {command code for \.{\\jobname}}
965 @d lower_cdigit_base=10 {lowercase style Chinese number}
966 @d upper_cdigit_base=25 {uppercase style Chinese number}
970 primitive("jobname",convert,job_name_code);@/
971 @!@:job_name_}{\.{\\jobname} primitive@>
973 primitive("jobname",convert,job_name_code);@/
974 @!@:job_name_}{\.{\\jobname} primitive@>
975 primitive("PUXcnumber",convert,cnumber_code);@/
976 @!@:cnumber_}{\.{\\PUXcnumber} primitive@>
977 primitive("PUXscnumber",convert,scnumber_code);@/
978 @!@:scnumber_}{\.{\\PUXscnumber} primitive@>
979 primitive("PUXucnumber",convert,ucnumber_code);@/
980 @!@:ucnumber_}{\.{\\PUXucnumber} primitive@>
981 primitive("PUXfcnumber",convert,fcnumber_code);@/
982 @!@:fcnumber_}{\.{\\PUXfcnumber} primitive@>
983 primitive("PUXacnumber",convert,acnumber_code);@/
984 @!@:acnumber_}{\.{\\PUXacnumber} primitive@>
985 primitive("PUXcjknumber",convert,cjknumber_code);@/
986 @!@:cjknumber_}{\.{\\PUXcjknumber} primitive@>
987 primitive("PUXnameseq",convert,nameseq_code);@/
988 @!@:cjknameseq_}{\.{\\PUXnameseq} primitive@>
992 meaning_code: print_esc("meaning");
993 font_name_code: print_esc("fontname");
995 meaning_code: print_esc("meaning");
996 font_name_code: print_esc("fontname");
997 cnumber_code: print_esc("PUXcnumber");
998 scnumber_code: print_esc("PUXscnumber");
999 ucnumber_code: print_esc("PUXucnumber");
1000 fcnumber_code: print_esc("PUXfcnumber");
1001 acnumber_code: print_esc("PUXfanumber");
1002 cjknumber_code: print_esc("PUXcjknumber");
1003 nameseq_code: print_esc("PUXnameseq");
1007 @!save_scanner_status:small_number; {|scanner_status| upon entry}
1008 @!b:pool_pointer; {base of temporary string}
1009 begin c:=cur_chr; @<Scan the argument for command |c|@>;
1011 @!save_scanner_status:small_number; {|scanner_status| upon entry}
1012 @!b:pool_pointer; {base of temporary string}
1014 @!saved_val,digit_base,sign:integer;
1015 @!min_val,max_val,offset:integer;
1016 begin c:=cur_chr; @<Scan the argument for command |c|@>;
1021 number_code,roman_numeral_code: scan_int;
1024 number_code,roman_numeral_code,cnumber_code,scnumber_code,ucnumber_code,
1025 fcnumber_code : scan_int;
1026 acnumber_code: @<scan and split the number@>;
1027 cjknumber_code:@<scan a CJK number with a possible selector and then split it@>;
1028 nameseq_code:@<scan a CJK name sequence number@>;
1032 roman_numeral_code: print_roman_int(cur_val);
1033 string_code:if cur_cs<>0 then sprint_cs(cur_cs)
1034 else print_char(cur_chr);
1036 roman_numeral_code: print_roman_int(cur_val);
1037 cnumber_code: print_chinese_int(cur_val,lower_cdigit_base,false,false);
1038 scnumber_code: print_chinese_int(cur_val,lower_cdigit_base,true,false);
1039 ucnumber_code: print_chinese_int(cur_val,upper_cdigit_base,false,false);
1040 fcnumber_code: print_chinese_int(cur_val,upper_cdigit_base,false,true);
1041 acnumber_code: @<using full-width arabic characters to print a CJK number@>;
1042 cjknumber_code: @<print a CJK number with specified format@>;
1043 nameseq_code: @<print a CJK name sequence member@>;
1044 string_code:if cur_cs<>0 then sprint_cs(cur_cs)
1046 if is_wchar(cur_chr) then print_wchar(cur_chr)
1047 else print_char(cur_chr);
1051 font_name_code: begin print(font_name[cur_val]);
1052 if font_size[cur_val]<>font_dsize[cur_val] then
1053 begin print(" at "); print_scaled(font_size[cur_val]);
1058 font_name_code: begin
1059 if cur_val <=font_max then begin
1060 print(font_name[cur_val]);
1061 if font_size[cur_val]<>font_dsize[cur_val] then
1062 begin print(" at "); print_scaled(font_size[cur_val]);
1068 print(cface[cfont_face[cur_val]]);
1069 dsize:=cfont_dsize[cur_val] div @"10000;
1071 if cfont_size[cur_val]<>cfont_dsize[cur_val] then
1072 begin print(" at "); print_scaled(cfont_size[cur_val]);
1080 if (cur_cmd>active_char)or(cur_chr>255) then {not a character}
1081 begin m:=relax; n:=256;
1083 if (cur_cmd>active_char)or(cur_chr>65535) then {not a character}
1084 begin m:=relax; n:=256; {values other than 256 will break latex.fmt}
1088 if (cur_cmd>active_char)or(cur_chr>255) then
1089 begin cur_cmd:=relax; cur_chr:=256;
1092 if (cur_cmd>active_char)or(cur_chr>65535) then
1093 begin cur_cmd:=relax; cur_chr:=256; {values other than 256 will break latex.fmt}
1098 pack_job_name(".dvi");
1099 while not b_open_out(dvi_file) do
1100 prompt_file_name("file name for output",".dvi");
1102 pack_job_name(".cdi");
1103 while not b_open_out(dvi_file) do
1104 prompt_file_name("file name for output",".cdi");
1108 @ Before we forget about the format of these tables, let's deal with two
1109 of \TeX's basic scanning routines related to font information.
1111 @<Declare procedures that scan font-related stuff@>=
1112 procedure scan_font_ident;
1113 var f:internal_font_number;
1115 begin @<Get the next non-blank non-call...@>;
1116 if cur_cmd=def_font then f:=cur_font
1117 else if cur_cmd=set_font then f:=cur_chr
1119 @ Before we forget about the format of these tables, let's deal with two
1120 of \TeX's basic scanning routines related to font information.
1122 TCW: handle the commands |def_cfont| and |set_cfont|.
1124 @<Declare procedures that scan font-related stuff@>=
1125 procedure scan_font_ident;
1128 begin @<Get the next non-blank non-call...@>;
1129 if cur_cmd=def_font then f:=cur_font
1130 else if cur_cmd=set_font or cur_cmd=set_cfont then f:=cur_chr
1134 bytes long, so it is in the range |0<=c<65536|. \TeX82 never uses this
1135 command, but it should come in handy for extensions of \TeX\ that deal
1136 with oriental languages.
1138 bytes long, so it is in the range |0<=c<65536|. \PUTeX\ uses this to typeset
1139 a CJK two-byte character.
1143 \yskip\hang|pre| 247 |i[1]| |num[4]| |den[4]| |mag[4]| |k[1]| |x[k]|.
1144 Beginning of the preamble; this must come at the very beginning of the
1145 file. Parameters |i|, |num|, |den|, |mag|, |k|, and |x| are explained below.
1147 \yskip\hang|pre| 247 |i[1]| |c[1]| |num[4]| |den[4]| |mag[4]| |k[1]| |x[k]|.
1148 Beginning of the preamble; this must come at the very beginning of the
1149 file. Parameters |i|, |c|, |num|, |den|, |mag|, |k|, and |x| are explained below.
1153 \yskip\hang|post_post| 249. Ending of the postamble, see below.
1155 \yskip\noindent Commands 250--255 are undefined at the present time.
1157 \yskip\hang|post_post| 249. Ending of the postamble, see below.
1159 \yskip\hang|cfnt| 250 |k[2]|. Set |cf:=k|. \PUTeX\ uses this command for CJK font
1160 numbers in the range |0<=k<65535|.
1162 \yskip\hang|cfnt_def| 251 |k[2]| |l[1]| |n[l]| |c[1]| |s[4]| |ds[4]| |wt[2]| |y[1]|
1163 |w[4]| |h[4]| |d[4]| |fw[4]| |fh[4]| |fd[4]|. Define CJK font |k|, where |0<=k<65536|, see below.
1165 \yskip\noindent Commands 252--255 are undefined at the present time.
1169 @d set1=128 {typeset a character and move right}
1171 @d set1=128 {typeset a character and move right}
1172 @d set2=129 {typeset a two-byte CJK character and move right}
1173 @d set4=131 {typeset a four-byte CJK character and move right}
1177 @d post_post=249 {postamble ending}
1179 @d post_post=249 {postamble ending}
1180 @d cfnt=250 {set current chinese font}
1181 @d cfnt_def=251 {define the meaning of a chinese font}
1185 $$\hbox{|@!i[1]| |@!num[4]| |@!den[4]| |@!mag[4]| |@!k[1]| |@!x[k]|.}$$
1186 The |i| byte identifies \.{DVI} format; currently this byte is always set
1187 to~2. (The value |i=3| is currently used for an extended format that
1188 allows a mixture of right-to-left and left-to-right typesetting.
1189 Some day we will set |i=4|, when \.{DVI} format makes another
1190 incompatible change---perhaps in the year 2048.)
1192 $$\hbox{|@!i[1]| |@!c[1]| |@!num[4]| |@!den[4]| |@!mag[4]| |@!k[1]| |@!x[k]|.}$$
1193 The |i| byte identifies \.{CDI} format; currently this byte is always set
1194 to~100. (Some day we will set |i=101|, when \.{CDI} format makes another
1195 incompatible change---perhaps in the year 2048.)
1197 The |c| byte identifies the default character code set of document. Currently, the following
1198 code value is defined:
1200 0: USC2 (Unicode, not supported yet)
1202 1: Big5 (Traditional Chinese used in Taiwan and Hong Kong)
1204 2: GBK (Simplified Chinese used in PRC and Singapore)
1208 @d id_byte=2 {identifies the kind of \.{DVI} files described here}
1210 @d id_byte=100 {identifies the kind of \.{DVI} files described here}
1214 @ Here's a procedure that outputs a font definition. Since \TeX82 uses at
1215 most 256 different fonts per job, |fnt_def1| is always used as the command code.
1217 @ Here's a procedure that outputs a font definition. Since \TeX82 uses at
1218 most 256 different fonts per job, |fnt_def1| is always used as the command code.
1220 TCW: the procedure |dvi_cfont_def| outputs a chinese font definition.
1224 @<Output the font name whose internal number is |f|@>;
1227 @<Output the font name whose internal number is |f|@>;
1230 procedure dvi_cfont_def (f:internal_cfont_number);
1236 dvi_out((f-cfont_base-1) div 256); dvi_out((f-cfont_base-1) mod 256);
1237 {Output the CJK font face name}
1238 dvi_out(length(cface_name[j]));
1239 for k:= str_start[cface_name[j]] to str_start[cface_name[j]+1] - 1 do dvi_out(str_pool[k]);
1240 dvi_out(cface_charset[j]);
1241 dvi_four(cfont_size[f]);
1242 dvi_four(cfont_dsize[f]);
1243 dvi_out(cface_weight[j] div 256); dvi_out(cface_weight[j] mod 256);
1244 dvi_out(cface_style[j]);
1245 dvi_four(cfont_width[f]);
1246 dvi_four(cfont_height[f]);
1247 dvi_four(cfont_depth[f]);
1248 dvi_four(cface_fw_width[j]);
1249 dvi_four(cface_fw_height[j]);
1250 dvi_four(cface_fw_depth[j]);
1255 dvi_h:=0; dvi_v:=0; cur_h:=h_offset; dvi_f:=null_font;
1257 dvi_h:=0; dvi_v:=0; cur_h:=h_offset; dvi_f:=null_font; dvi_cf:=null_cfont;
1261 begin dvi_out(pre); dvi_out(id_byte); {output the preamble}
1263 begin dvi_out(pre); dvi_out(id_byte);
1264 doc_charset:=pux_charset; dvi_out(doc_charset); {output the preamble}
1268 print(" TeX output "); print_int(year); print_char(".");
1270 print(" PUTeX output "); print_int(year); print_char(".");
1275 @<Output node |p| for |hlist_out|...@>=
1276 reswitch: if is_char_node(p) then
1277 begin synch_h; synch_v;
1278 repeat f:=font(p); c:=character(p);
1279 if f<>dvi_f then @<Change font |dvi_f| to |f|@>;
1280 if font_ec[f]>=qo(c) then if font_bc[f]<=qo(c) then
1281 if char_exists(orig_char_info(f)(c)) then {N.B.: not |char_info|}
1282 begin if c>=qi(128) then dvi_out(set1);
1284 cur_h:=cur_h+char_width(f)(orig_char_info(f)(c));
1287 if mltex_enabled_p then
1288 @<Output a substitution, |goto continue| if not possible@>;
1291 until not is_char_node(p);
1294 else @<Output the non-|char_node| |p| for |hlist_out|
1295 and move to the next node@>
1297 @<Output node |p| for |hlist_out|...@>=
1298 reswitch: if is_char_node(p) then
1299 begin synch_h; synch_v;
1300 repeat f:=font(p); c:=character(p);
1301 if (is_wchar(c)) then begin
1302 if f<>dvi_cf then @<Change font |dvi_cf| to |f|@>;
1303 dvi_out(set2); dvi_out(c div 256); dvi_out(c mod 256);
1304 cur_h:=cur_h+cfont_width[f];
1307 if f<>dvi_f then @<Change font |dvi_f| to |f|@>;
1308 if font_ec[f]>=qo(c) then if font_bc[f]<=qo(c) then
1309 if char_exists(orig_char_info(f)(c)) then {N.B.: not |char_info|}
1310 if c>=qi(128) then dvi_out(set1);
1312 cur_h:=cur_h+char_width(f)(orig_char_info(f)(c));
1315 if mltex_enabled_p then
1316 @<Output a substitution, |goto continue| if not possible@>;
1319 until not is_char_node(p);
1322 else @<Output the non-|char_node| |p| for |hlist_out|
1323 and move to the next node@>
1327 dvi_out(post_post); dvi_four(last_bop); dvi_out(id_byte);@/
1329 @<Output the CJK font definitions for all fonts that were used@>;
1330 dvi_out(post_post); dvi_four(last_bop); dvi_out(doc_charset); dvi_out(id_byte);@/
1334 @<Incorporate character dimensions into the dimensions of the hbox...@>=
1335 begin f:=font(p); i:=char_info(f)(character(p)); hd:=height_depth(i);
1336 x:=x+char_width(f)(i);@/
1337 s:=char_height(f)(hd);@+if s>h then h:=s;
1338 s:=char_depth(f)(hd);@+if s>d then d:=s;
1342 @<Incorporate character dimensions into the dimensions of the hbox...@>=
1343 begin f:=font(p); c:=character(p);
1344 if (is_wchar(c)) then begin
1345 x:=x+cfont_width[f];@/
1346 s:=cfont_height[f];@+if s>h then h:=s;
1347 s:=cfont_depth[f];@+if s>d then d:=s;
1350 i:=char_info(f)(c); hd:=height_depth(i);
1351 x:=x+char_width(f)(i);@/
1352 s:=char_height(f)(hd);@+if s>h then h:=s;
1353 s:=char_depth(f)(hd);@+if s>d then d:=s;
1360 font_in_short_display:=null_font; short_display(list_ptr(r)); print_ln;@/
1362 font_in_short_display:=null_font; cfont_in_short_display:=null_cfont;@/
1363 short_display(list_ptr(r)); print_ln;@/
1367 if (is_char_node(p))and(link(p)=null) then
1368 begin f:=font(p); v:=char_width(f)(char_info(f)(character(p)));
1369 if v<>width(b) then link(p):=new_kern(width(b)-v);
1372 if (is_char_node(p))and(link(p)=null) then
1375 if is_wchar_node(p) then
1378 v:=char_width(f)(char_info(f)(character(p)));
1379 if v<>width(b) then link(p):=new_kern(width(b)-v);
1384 if is_char_node(v) then
1386 break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v)));
1389 if is_char_node(v) then
1391 if is_wchar_node(v) then
1392 break_width[1]:=break_width[1]-cfont_width[f]
1394 break_width[1]:=break_width[1]-char_width(f)(char_info(f)(character(v)));
1399 ligature_node: begin f:=font(lig_char(v));@/
1400 break_width[1]:=@|break_width[1]-
1401 char_width(f)(char_info(f)(character(lig_char(v))));
1404 ligature_node: begin f:=font(lig_char(v));@/
1405 if is_wchar(character(lig_char(v))) then
1406 break_width[1]:=@|break_width[1]-cfont_width[f]
1408 break_width[1]:=@|break_width[1]-
1409 char_width(f)(char_info(f)(character(lig_char(v))));
1414 if is_char_node(s) then
1416 break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s)));
1419 if is_char_node(s) then
1421 if is_wchar_node(s) then
1422 break_width[1]:=break_width[1]+cfont_width[f]
1424 break_width[1]:=@|break_width[1]+char_width(f)(char_info(f)(character(s)));
1429 ligature_node: begin f:=font(lig_char(s));
1430 break_width[1]:=break_width[1]+
1431 char_width(f)(char_info(f)(character(lig_char(s))));
1434 ligature_node: begin f:=font(lig_char(s));@/
1435 if is_wchar(character(lig_char(s))) then
1436 break_width[1]:=break_width[1]+cfont_width[f]
1438 break_width[1]:=break_width[1]+
1439 char_width(f)(char_info(f)(character(lig_char(s))));
1444 font_in_short_display:=null_font
1446 cfont_in_short_display:=null_cfont; font_in_short_display:=null_font
1450 ligature_node: begin f:=font(lig_char(cur_p));
1451 act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p))));
1454 ligature_node: begin f:=font(lig_char(cur_p));
1455 if is_wchar(character(lig_char(cur_p))) then
1456 act_width:=act_width+cfont_width[f]
1458 act_width:=act_width+char_width(f)(char_info(f)(character(lig_char(cur_p))));
1463 repeat f:=font(cur_p);
1464 act_width:=act_width+char_width(f)(char_info(f)(character(cur_p)));
1466 until not is_char_node(cur_p);
1469 repeat f:=font(cur_p);
1470 if is_wchar_node(cur_p) then
1471 act_width:=act_width+cfont_width[f]
1473 act_width:=act_width+char_width(f)(char_info(f)(character(cur_p)));
1475 until not is_char_node(cur_p);
1480 if is_char_node(s) then
1482 disc_width:=disc_width+char_width(f)(char_info(f)(character(s)));
1485 if is_char_node(s) then
1487 if is_wchar_node(s) then
1488 disc_width:=disc_width+cfont_width[f]
1490 disc_width:=disc_width+char_width(f)(char_info(f)(character(s)));
1495 ligature_node: begin f:=font(lig_char(s));
1496 disc_width:=disc_width+
1497 char_width(f)(char_info(f)(character(lig_char(s))));
1500 ligature_node: begin f:=font(lig_char(s));
1501 if is_wchar(character(lig_char(s))) then
1502 disc_width:=disc_width+cfont_width[f]
1504 disc_width:=disc_width+
1505 char_width(f)(char_info(f)(character(lig_char(s))));
1510 if is_char_node(s) then
1512 act_width:=act_width+char_width(f)(char_info(f)(character(s)));
1515 if is_char_node(s) then
1517 if is_wchar_node(s) then
1518 act_width:=act_width+cfont_width[f]
1520 act_width:=act_width+char_width(f)(char_info(f)(character(s)));
1525 ligature_node: begin f:=font(lig_char(s));
1526 act_width:=act_width+
1527 char_width(f)(char_info(f)(character(lig_char(s))));
1530 ligature_node: begin f:=font(lig_char(s));
1531 if is_wchar(character(lig_char(s))) then
1532 act_width:=act_width+cfont_width[f]
1534 act_width:=act_width+
1535 char_width(f)(char_info(f)(character(lig_char(s))));
1540 char_num: begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
1543 spacer,right_brace: begin if n>1 then @<Enter a hyphenation exception@>;
1545 char_num: begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
1548 pux_char_given:@<Give improper hyphenation error for Chinese characters inside@>;
1549 pux_char_num: begin scan_wchar_num; cur_chr:=cur_val; cur_cmd:=pux_char_given;
1552 spacer,right_brace: begin if n>1 then @<Enter a hyphenation exception@>;
1556 if cur_chr="-" then @<Append the value |n| to list |p|@>
1557 else begin if lc_code(cur_chr)=0 then
1558 begin print_err("Not a letter");
1560 help2("Letters in \hyphenation words must have \lccode>0.")@/
1561 ("Proceed; I'll ignore the character I just read.");
1565 begin incr(n); hc[n]:=lc_code(cur_chr);
1569 if cur_chr="-" then @<Append the value |n| to list |p|@>
1570 else begin if is_wchar(cur_chr) then
1571 begin print_err("Chinese character can't appear here");
1573 help2("Letters in \hyphenation words can't be Chinese characters.")@/
1574 ("Proceed; I'll ignore the character I just read.");
1577 else if lc_code(cur_chr)=0 then
1578 begin print_err("Not a letter");
1580 help2("Letters in \hyphenation words must have \lccode>0.")@/
1581 ("Proceed; I'll ignore the character I just read.");
1585 begin incr(n); hc[n]:=lc_code(cur_chr);
1591 @d main_loop=70 {go here to typeset a string of consecutive characters}
1593 @d main_loop=70 {go here to typeset a string of consecutive characters}
1594 @d main_loop_wchar=130 {go here to typeset a string of consecutive double-byte characters}
1595 @d save_cur_wchar=132 {go here to typeset a double-byte characters}
1596 @d next_is_a_char=133 {go here if next token is a single-byte character}
1597 @d fetch_next_tok=134 {go here to fetch next token}
1601 @t\4@>@<Declare the procedure called |handle_right_brace|@>@;
1602 procedure main_control; {governs \TeX's activities}
1604 @t\4@>@<Declare the procedure called |handle_right_brace|@>@;
1605 procedure main_control; {governs \TeX's activities}
1609 label big_switch,reswitch,main_loop,main_loop_wrapup,
1611 label big_switch,reswitch,main_loop_wchar,main_loop_wchar+1,save_cur_wchar,
1612 next_is_a_char,fetch_next_tok,main_loop,main_loop+1,
1613 main_loop_wrapup,main_loop_lookahead+2,
1617 var@!t:integer; {general-purpose temporary variable}
1618 begin if every_job<>null then begin_token_list(every_job,every_job_text);
1619 big_switch: get_x_token;@/
1621 var@!t:integer; {general-purpose temporary variable}
1622 begin if every_job<>null then begin_token_list(every_job,every_job_text);
1623 @<Initialization of global variables done in the |main_control| procedure@>@;
1624 big_switch: get_x_token;@/
1628 hmode+letter,hmode+other_char,hmode+char_given: goto main_loop;
1630 hmode+letter,hmode+other_char,hmode+char_given:
1631 if is_wchar(cur_chr) then goto main_loop_wchar
1632 else goto main_loop;
1633 hmode+pux_char_given: goto main_loop_wchar;
1637 hmode+char_num: begin scan_char_num; cur_chr:=cur_val; goto main_loop;@+end;
1638 hmode+no_boundary: begin get_x_token;
1639 if (cur_cmd=letter)or(cur_cmd=other_char)or(cur_cmd=char_given)or
1640 (cur_cmd=char_num) then cancel_boundary:=true;
1644 hmode+char_num: begin scan_char_num; cur_chr:=cur_val; goto main_loop;@+end;
1645 hmode+pux_char_num: begin scan_wchar_num; cur_chr:=cur_val; goto main_loop_wchar;@+end;
1646 hmode+no_boundary: begin get_x_token;
1647 if (cur_cmd=letter)or(cur_cmd=other_char)or(cur_cmd=char_given)or
1648 (cur_cmd=char_num)or(cur_cmd=pux_char_num)or(cur_cmd=pux_char_given) then cancel_boundary:=true;
1654 hmode+spacer: if space_factor=1000 then goto append_normal_space
1656 hmode+ex_space,mmode+ex_space: goto append_normal_space;
1658 @t\4@>@<Cases of |main_control| that handle spacer@>@;
1662 main_loop:@<Append character |cur_chr| and the following characters (if~any)
1664 main_loop_wchar:@<Append double-byte character |cur_chr| and the following double-byte characters
1665 (if~any) to the current hlist in the current font; |goto main_loop| when a single-byte character
1666 has been fetched; |goto reswitch| when a non-character has been fetched@>;
1667 main_loop:@<Append character |cur_chr| and the following characters (if~any)
1671 @d adjust_space_factor==@t@>@;@/
1672 main_s:=sf_code(cur_chr);
1674 @d adjust_space_factor==@t@>@;@/
1675 if (cur_chr < 256) then main_s:=sf_code(cur_chr)
1680 adjust_space_factor;@/
1683 main_cf:=cur_cfont; {in case the first letter is not a Chinese character}
1684 @<If the preceding node is wchar node, then append a cespace@>;
1685 main_loop+1:adjust_space_factor; main_f:=cur_font;
1689 get_next; {set only |cur_cmd| and |cur_chr|, for speed}
1690 if cur_cmd=letter then goto main_loop_lookahead+1;
1691 if cur_cmd=other_char then goto main_loop_lookahead+1;
1692 if cur_cmd=char_given then goto main_loop_lookahead+1;
1693 x_token; {now expand and set |cur_cmd|, |cur_chr|, |cur_tok|}
1694 if cur_cmd=letter then goto main_loop_lookahead+1;
1695 if cur_cmd=other_char then goto main_loop_lookahead+1;
1696 if cur_cmd=char_given then goto main_loop_lookahead+1;
1697 if cur_cmd=char_num then
1698 begin scan_char_num; cur_chr:=cur_val; goto main_loop_lookahead+1;
1700 if cur_cmd=no_boundary then bchar:=non_char;
1701 cur_r:=bchar; lig_stack:=null; goto main_lig_loop;
1702 main_loop_lookahead+1: adjust_space_factor;
1703 fast_get_avail(lig_stack); font(lig_stack):=main_f;
1704 cur_r:=qi(cur_chr); character(lig_stack):=cur_r;
1705 if cur_r=false_bchar then cur_r:=non_char {this prevents spurious ligatures}
1707 @<Look ahead for next character. If it is a wide character then append
1708 a cespace, or leave |lig_stack| empty if there's no character there@>
1712 else temp_ptr:=new_param_glue(space_skip_code);
1713 link(tail):=temp_ptr; tail:=temp_ptr;
1716 else temp_ptr:=new_param_glue(space_skip_code);
1717 link(tail):=temp_ptr; tail:=temp_ptr;
1718 if pux_xspace=0 then goto reswitch else goto big_switch
1722 hbox_group: package(0);
1723 adjusted_hbox_group: begin adjust_tail:=adjust_head; package(0);
1726 hbox_group: @<Setup |hbox_tail| and package@>;
1727 adjusted_hbox_group: begin adjust_tail:=adjust_head;
1728 @<Setup |hbox_tail| and package@>;
1733 vmode+start_par: new_graf(cur_chr>0);
1734 vmode+letter,vmode+other_char,vmode+char_num,vmode+char_given,
1735 vmode+math_shift,vmode+un_hbox,vmode+vrule,
1737 vmode+start_par: new_graf(cur_chr>0);
1738 vmode+letter,vmode+other_char,vmode+char_num,vmode+char_given,
1739 vmode+pux_char_num,vmode+pux_char_given,
1740 vmode+math_shift,vmode+un_hbox,vmode+vrule,
1744 begin if tail<>head then
1745 begin if is_char_node(tail) then p:=tail
1747 begin if tail<>head then
1748 begin if is_char_node(tail) and not is_wchar_node(tail) then p:=tail
1752 reswitch: if is_char_node(p) then
1753 begin f:=font(p); d:=char_width(f)(char_info(f)(character(p)));
1757 reswitch: if is_char_node(p) then
1759 if is_wchar_node(p) then
1762 d:=char_width(f)(char_info(f)(character(p)));
1768 letter,other_char,char_given: begin c:=ho(math_code(cur_chr));
1770 begin @<Treat |cur_chr| as an active character@>;
1775 letter,other_char,char_given: begin
1776 if is_wchar(cur_chr) then begin
1777 print_err("Chinese character is ignored in math mode");
1778 help1("Did you forget putting it into an \hbox?");
1783 c:=ho(math_code(cur_chr));
1785 begin @<Treat |cur_chr| as an active character@>;
1793 char_num: begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
1797 char_num: begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
1800 pux_char_num: begin scan_wchar_num; cur_chr:=cur_val; cur_cmd:=pux_char_given;
1803 pux_char_given:begin print_err("Chinese character is ignored in math mode");
1804 help1("Did you forget putting it into an \hbox?");
1811 mmode+letter,mmode+other_char,mmode+char_given:
1812 set_math_char(ho(math_code(cur_chr)));
1814 mmode+letter,mmode+other_char,mmode+char_given:
1815 if is_wchar(cur_chr) then begin
1816 print_err("Chinese character is ignored in math mode");
1817 help1("Did you forget putting it into an \hbox?");
1821 set_math_char(ho(math_code(cur_chr)));
1825 letter,other_char: cur_val:=del_code(cur_chr);
1828 if is_wchar(cur_chr) then
1831 cur_val:=del_code(cur_chr);
1835 mmode+math_shift: if cur_group=math_shift_group then after_math
1838 mmode+math_shift: if cur_group=math_shift_group then begin
1840 if math_mode_save<0 then begin
1842 @<If the token is a wide character, then append a cspace@>;
1850 tail_append(new_math(math_surround,after));
1851 space_factor:=1000; unsave;
1855 tail_append(new_math(math_surround,after));
1856 space_factor:=1000; unsave;
1866 any_mode(set_cfont),
1867 any_mode(pux_cface_def),
1868 any_mode(pux_face_match),
1869 any_mode(pux_font_match),
1870 any_mode(pux_set_cface),
1871 any_mode(puxg_assign_flag),
1872 any_mode(puxg_assign_int),
1873 any_mode(pux_get_int),
1874 any_mode(pux_set_cface_attrib),
1875 any_mode(pux_set_cfont_attrib),
1876 any_mode(pux_range_catcode),
1877 any_mode(pux_range_type_code),
1878 any_mode(pux_split_number),
1879 any_mode(puxg_assign_space),
1880 any_mode(pux_set_default_cface),
1881 any_mode(pux_dump_font_info),
1885 @t\4@>@<Declare subprocedures for |prefixed_command|@>@t@>@;@/
1886 procedure prefixed_command;
1888 @t\4@>@<Declare PUTeX subprocedures for |prefixed_command|@>@t@>@;@/
1889 @t\4@>@<Declare subprocedures for |prefixed_command|@>@t@>@;@/
1890 procedure prefixed_command;
1894 @!n:integer; {ditto}
1895 @!e:boolean; {should a definition be expanded? or was \.{\\let} not done?}
1897 @!n:integer; {ditto}
1898 @!e:boolean; {should a definition be expanded? or was \.{\\let} not done?}
1899 @<Other variables used by the procedure |prefixed_command|@>@;
1903 set_font: define(cur_font_loc,data,cur_chr);
1905 set_font: begin define(cur_font_loc,data,cur_chr);@/
1906 @<Set the matching CJK font@>;
1911 @d toks_def_code=6 {|shorthand_def| for \.{\\toksdef}}
1913 @d toks_def_code=6 {|shorthand_def| for \.{\\toksdef}}
1914 @d pux_char_def_code=7 {|shorthand_def| for \.{\\PUXchardef}}
1918 primitive("toksdef",shorthand_def,toks_def_code);@/
1919 @!@:toks_def_}{\.{\\toksdef} primitive@>
1921 primitive("toksdef",shorthand_def,toks_def_code);@/
1922 @!@:toks_def_}{\.{\\toksdef} primitive@>
1923 primitive("PUXchardef",shorthand_def,pux_char_def_code);@/
1924 @!@:pux_char_def_}{\.{\\toksdef} primitive@>
1928 mu_skip_def_code: print_esc("muskipdef");
1929 char_sub_def_code: print_esc("charsubdef");
1930 othercases print_esc("toksdef")
1932 mu_skip_def_code: print_esc("muskipdef");
1933 char_sub_def_code: print_esc("charsubdef");
1934 toks_def_code: print_esc("toksdef");
1935 othercases print_esc("PUXchardef")
1940 char_def_code: begin scan_char_num; define(p,char_given,cur_val);
1942 math_char_def_code: begin scan_fifteen_bit_int; define(p,math_given,cur_val);
1944 othercases begin scan_eight_bit_int;
1947 char_def_code: begin scan_char_num; define(p,char_given,cur_val);
1949 math_char_def_code: begin scan_fifteen_bit_int; define(p,math_given,cur_val);
1951 pux_char_def_code: begin scan_wchar_num; define(p,pux_char_given,cur_val);
1953 othercases begin scan_eight_bit_int;
1957 primitive("catcode",def_code,cat_code_base);
1958 @!@:cat_code_}{\.{\\catcode} primitive@>
1960 primitive("catcode",def_code,cat_code_base);
1961 @!@:cat_code_}{\.{\\catcode} primitive@>
1962 primitive("PUXcatcode",def_code,pux_cat_code_base);
1963 @!@:pux_cat_code_}{\.{\\PUXcatcode} primitive@>
1964 primitive("PUXtypecode",def_code,pux_type_code_base);
1965 @!@:pux_type_code_base_}{\.{\\PUXtypecode} primitive@>
1966 primitive("PUXlocalnames",def_code,pux_local_names_base);
1967 @!@:pux_local_names_base_}{\.{\\PUXlocalnames} primitive@>
1971 else if chr_code=math_code_base then print_esc("mathcode")
1973 else if chr_code=pux_cat_code_base then print_esc("PUXcatcode")
1974 else if chr_code=pux_type_code_base then print_esc("PUXtypecode")
1975 else if chr_code=pux_local_names_base then print_esc("PUXlocalnames")
1976 else if chr_code=math_code_base then print_esc("mathcode")
1980 p:=cur_chr; scan_char_num; p:=p+cur_val; scan_optional_equals;
1984 if p = pux_cat_code_base then
1985 begin scan_wchar_num; p := cat_code_base;
1987 else if p = pux_type_code_base then scan_wchar_num
1988 else if p = pux_local_names_base then scan_eight_bit_int
1991 p:=p+cur_val; scan_optional_equals;
1992 if p=pux_local_names_base then scan_wchar_num
1997 else if cur_chr=math_code_base then n:=@'100000
1999 else if cur_chr=pux_cat_code_base then n:=max_char_code
2000 else if cur_chr=pux_type_code_base then n:=max_type_code
2001 else if cur_chr=pux_local_names_base then n:=65535
2002 else if cur_chr=math_code_base then n:=@'100000
2006 set_box: begin scan_eight_bit_int;
2007 if global then n:=256+cur_val@+else n:=cur_val;
2008 scan_optional_equals;
2009 if set_box_allowed then scan_box(box_flag+n)
2010 else begin print_err("Improper "); print_esc("setbox");
2012 set_box: begin scan_eight_bit_int;
2013 if global then n:=256+cur_val@+else n:=cur_val;
2014 scan_optional_equals;
2015 if set_box_allowed then begin
2017 scan_box(box_flag+n);
2020 else begin print_err("Improper "); print_esc("setbox");
2024 procedure new_font(@!a:small_number);
2025 label common_ending;
2026 var u:pointer; {user's font identifier}
2027 @!s:scaled; {stated ``at'' size, or negative of scaled magnification}
2028 @!f:internal_font_number; {runs through existing fonts}
2029 @!t:str_number; {name for the frozen font identifier}
2030 @!old_setting:0..max_selector; {holds |selector| setting}
2031 begin if job_name=0 then open_log_file;
2032 {avoid confusing \.{texput} with the font name}
2034 get_r_token; u:=cur_cs;
2035 if u>=hash_base then t:=text(u)
2036 else if u>=single_base then
2037 if u=null_cs then t:="FONT"@+else t:=u-single_base
2038 else begin old_setting:=selector; selector:=new_string;
2039 print("FONT"); print(u-active_base); selector:=old_setting;
2041 str_room(1); t:=make_string;
2043 define(u,set_font,null_font); scan_optional_equals; scan_file_name;
2044 @<Scan the font size specification@>;
2045 @<If this font has already been loaded, set |f| to the internal
2046 font number and |goto common_ending|@>;
2047 f:=read_font_info(u,cur_name,cur_area,s);
2048 common_ending: equiv(u):=f; eqtb[font_id_base+f]:=eqtb[u]; font_id_text(f):=t;
2051 @<Declare the function called |fw_times_sd|@>@;
2052 @<Declare the function called |find_cface_num|@>@;
2053 @<Declare the procedure called |check_cfont|@>@;
2054 @<Declare the procedure called |make_cfont|@>@;
2055 procedure new_font(@!a:small_number);
2056 label common_ending;
2057 var u:pointer; {user's font identifier}
2059 @!s:scaled; {stated ``at'' size, or negative of scaled magnification}
2060 @!f:internal_font_number; {runs through existing fonts}
2061 @!t:str_number; {name for the frozen font identifier}
2062 @!old_setting:0..max_selector; {holds |selector| setting}
2063 @!flushable_string:str_number; {string not yet referenced}
2064 @<Other local variables used by procedure |new_font|@>@;
2065 begin if job_name=0 then open_log_file;
2066 {avoid confusing \.{texput} with the font name}
2068 get_r_token; u:=cur_cs;
2069 if u>=hash_base then t:=text(u)
2070 else if u>=single_base then
2071 if u=null_cs then t:="FONT"@+else t:=u-single_base
2072 else begin old_setting:=selector; selector:=new_string;
2073 print("FONT"); print(u-active_base); selector:=old_setting;
2075 str_room(1); t:=make_string;
2077 scan_optional_equals; scan_file_name;@/
2078 @<Scan the font size specification@>;
2079 if (length(cur_name) > 5) then
2081 j:=str_start[cur_name];
2082 if (str_pool[j]='C' and str_pool[j+1]='F' and str_pool[j+2]='O'
2083 and str_pool[j+3]='N' and str_pool[j+4]='T') then
2084 @<Define a CJK font and then goto |common_ending|@>;
2086 define(u,set_font,null_font);
2087 @<If this font has already been loaded, set |f| to the internal
2088 font number and |goto common_ending|@>;
2089 f:=read_font_info(u,cur_name,cur_area,s);
2090 common_ending: equiv(u):=f; eqtb[font_id_base+f]:=eqtb[u]; font_id_text(f):=t;
2095 @!t:halfword; {token}
2096 @!c:eight_bits; {character code}
2097 begin b:=cur_chr; p:=scan_toks(false,false); p:=link(def_ref);
2099 @!t:halfword; {token}
2100 @!c:quarterword; {character code}
2101 begin b:=cur_chr; p:=scan_toks(false,false); p:=link(def_ref);
2105 @<Change the case of the token in |p|, if a change is appropriate@>=
2107 if t<cs_token_flag+single_base then
2109 if equiv(b+c)<>0 then info(p):=t-c+equiv(b+c);
2112 @<Change the case of the token in |p|, if a change is appropriate@>=
2114 if t<cs_token_flag+single_base then
2115 begin c:=t mod 65536;
2116 if c < 256 then {only convert the single-byte char}
2117 if equiv(b+c)<>0 then info(p):=t-c+equiv(b+c);
2122 @<Dump the font information@>;
2124 @<Dump the font information@>;
2125 @<Dump the CJK font face information@>;
2126 @<Dump the face matching table@>;
2127 @<Dump the CJK font information@>;
2131 @<Undump the font information@>;
2133 @<Undump the font information@>;
2134 @<Undump the CJK font face information@>;
2135 @<Unump the face matching table@>;
2136 @<Undump the CJK font information@>;
2140 15: begin font_in_short_display:=null_font; short_display(n);
2142 15: begin font_in_short_display:=null_font; cfont_in_short_display:=null_cfont; short_display(n);
2148 @* \[55] Introduction to \PUTeX.
2149 \PUTeX is an extension of \TeX to handle CJK character sets.
2152 @!hi_byte, @!lo_byte : ASCII_code;
2153 {temp var for storing high byte and low byte of a double-byte character}
2154 @!db_char : quarterword; {temp var for storing a double-byte character}
2155 @!expand_char : boolean;
2156 @!doc_charset : eight_bits;
2157 @!char_val_flag : boolean;
2159 @ @<Set initial...@>=
2162 @ The default catcode for CJK characters is `letter'.
2164 @<Initialize table entries...@>=
2165 for k:= 256 to 65535 do
2166 begin cat_code(k) := letter;
2169 @ Initially, \PUTeX\ just set type codes for OT1 encoding.
2171 @d set_tail_forbidden(#) == set_type_code(#)(tail_forbidden)
2172 @d set_head_forbidden(#) == set_type_code(#)(head_forbidden)
2174 @<Initialize table entries...@>=
2175 set_tail_forbidden("(");
2176 set_tail_forbidden("[");
2177 set_tail_forbidden("{");@/
2178 set_head_forbidden("!");
2179 set_head_forbidden(")");
2180 set_head_forbidden(",");@/
2181 set_head_forbidden(".");
2182 set_head_forbidden(":");
2183 set_head_forbidden(";");@/
2184 set_head_forbidden("?");
2185 set_head_forbidden("]");
2186 set_head_forbidden("}");
2188 @ @<PUTeX routines...@>=
2189 function get_cat_code (ch:halfword) : halfword;
2190 var cat: halfword; {catcode}
2192 if pux_wcharother <> 0 then
2193 if ch > 255 then cat := other_char
2194 else cat := cat_code(ch)
2195 else cat := cat_code(ch);
2196 get_cat_code := cat;
2199 @ @<Put each of \TeX's primitives into the hash table@>=
2200 primitive("PUXrangecatcode",pux_range_catcode,0);
2201 primitive("PUXrangetypecode",pux_range_type_code,0);
2203 @ @<Other variables used by the procedure |prefixed_command|@>=
2204 @!bc, ec: halfword; {the begin char and end char of code range}
2207 pux_range_catcode, pux_range_type_code: begin
2209 if cur_cmd = pux_range_catcode then begin
2215 p:=pux_type_code_base;
2217 scan_wchar_num; bc := cur_val;@/
2218 scan_keyword("to");@/
2219 scan_wchar_num; ec := cur_val;@/
2220 scan_optional_equals;@/
2223 if (bc = 0) or (ec = 0) or (ec < bc) then begin
2224 if ec < bc then begin
2225 print_err("Invalid range setting, ec < bc");
2227 help1("I'm going to ignore this command.");@/
2229 goto exit; @.Invalid range@>
2232 if (cur_val < 0) or (cur_val > n) then begin
2233 print_err("Invalid catcode ("); print_int(cur_val);
2234 print("), should be in the range 0..15");@/
2235 help1("I'm going to ignore this command.");@/
2237 goto exit; @.Invalid code@>
2240 for k := bc to ec do define(p+k,data,cur_val);
2243 @ @<Initialize table entries...@>=
2244 for k:=0 to 255 do local_names(k) := "?";
2246 @ @<PUTeX basic scanning routines@>=
2247 function scan_name: str_number;
2249 @<Get the next non-blank non-call token@>;
2250 while cur_cmd=letter do
2252 if (is_wchar(cur_chr)) then append_wchar(cur_chr) else append_char(cur_chr);
2255 if pool_ptr <> str_start[str_ptr] then
2256 scan_name:=make_string
2261 @ @<Declare procedures that scan restricted classes of integers@>=
2262 procedure scan_wchar_num;
2264 if (cur_val<257)or(cur_val>65535) then
2265 begin print_err("Bad wide character code");
2266 @.Bad wide character code@>
2267 help2("A wide character number must be between 256 and 65536.")@/
2268 ("I changed this one to zero."); int_error(cur_val); cur_val:=0;
2272 @* \[56] CJK Numbers.
2274 @<Global variables@>=
2275 @!cnum_one_flag:boolean;
2278 @d ten_wchar_offset=10
2279 @d hundred_wchar_offset=11
2280 @d thousand_wchar_offset=12
2281 @d ten_thousand_wchar_offset=13
2282 @d hundred_million_wchar_offset=14
2283 @d arabic_wchar_offset=40
2284 @d negative_wchar_offset=50
2285 @d negative_wsym_offset=51
2286 @d twenty_wchar_offset=52
2287 @d thirty_wchar_offset=53
2288 @d CJK_digit_offset=0
2289 @d C_simple_digit_offset=10
2290 @d C_formal_digit_offset=25
2291 @d C_arabic_digit_offset=40
2295 procedure print_chinese_int (@!n,@!digit_base:integer;@!simple,@!formal:boolean);
2298 cnum_one_flag:=false;
2300 {|print_dbchar| is replaced by the following 2 |print_char| calls. }
2301 print_wchar(local_names(negative_wchar_offset));
2304 if n<100 then print_small_chinese_int(n,digit_base,simple,formal)
2306 if n>99999999 then begin
2307 print_small_chinese_int(n div 100000000,digit_base,simple,formal);
2308 print_wchar(local_names(digit_base+hundred_million_wchar_offset));
2309 cnum_one_flag:=true;
2311 if n>0 and n<10000000 then
2312 print_wchar(local_names(digit_base)); {zero character in Chinese}
2314 if n>9999 then begin
2315 print_medium_chinese_int(n div 10000,digit_base,simple,formal);
2316 print_wchar(local_names(digit_base+ten_thousand_wchar_offset));
2317 cnum_one_flag:=true;
2319 if n>0 and n<1000 then
2320 print_wchar(local_names(digit_base)); {zero character in Chinese}
2322 print_medium_chinese_int(n,digit_base,simple,formal);
2326 @ The following procedure prints a number n, $0\le n \le 99$.
2328 procedure print_small_chinese_int (n,@!digit_base:integer;@!simple,@!formal:boolean);
2331 if n<10 then print_wchar(local_names(n+digit_base))
2334 if formal or cnum_one_flag then
2335 print_wchar(local_names(digit_base+1));
2336 print_wchar(local_names(digit_base+10));@/
2339 if n<30 and simple then begin
2340 print_wchar(local_names(twenty_wchar_offset));@/
2343 if n<40 and simple then begin
2344 print_wchar(local_names(thirty_wchar_offset));@/
2347 print_wchar(local_names(digit_base + n div 10));
2348 print_wchar(local_names(digit_base+10));
2350 if n>0 then print_wchar(local_names(n+digit_base));
2354 @ Print a chinese number of medium size.
2356 procedure print_medium_chinese_int (n,@!digit_base:integer;@!simple,@!formal:boolean);
2359 print_wchar(local_names(digit_base+n div 1000));
2360 print_wchar(local_names(digit_base+thousand_wchar_offset));
2362 if n>0 and n<99 then
2363 print_wchar(local_names(digit_base)); {zero character in Chinese}
2366 print_wchar(local_names(digit_base+n div 100));
2367 print_wchar(local_names(digit_base+hundred_wchar_offset));
2370 print_wchar(local_names(digit_base)); {zero character in Chinese}
2372 cnum_one_flag:=true;
2373 if n>0 then print_small_chinese_int(n,digit_base,simple,formal);
2376 @ @<Put each of \TeX's primitives into the hash table@>=
2377 primitive("puxnumdigits",pux_get_int,int_base+pux_digit_num_code);
2378 primitive("puxsign",pux_get_int,int_base+pux_sign_code);
2379 primitive("puxdigit",pux_get_int,int_base+pux_digit_base);
2381 @ @<Cases of |print_cmd_chr|...@>=
2383 if chr_code=pux_digit_num_code+int_base then
2384 print_esc("puxnumdigits")
2385 else if chr_code=pux_sign_code+int_base then
2386 print_esc("puxsign")
2387 else if chr_code=pux_digit_base+int_base then
2388 print_esc("puxdigit");
2392 print_err("You can't assign values to internal read-only parameters.");
2396 @ @<scan \PUTeX\ internal values@>=
2398 if m=pux_digit_base+int_base then begin
2400 if cur_val < 0 or cur_val > 9 then begin
2401 print_err("Improper digit place specified (");
2402 print_int(cur_val); print("), replaced by 0");
2407 scanned_result(eqtb[m].int)(int_val);
2410 @ @<Put each of \TeX's primitives into the hash table@>=
2411 primitive("PUXsplitnumber",pux_split_number,0);
2414 pux_split_number: begin
2416 split_number(cur_val);
2419 @ The following procedure splits the integer parameter |n| to digit list and stores the number of digits into
2420 |pux_digit_num|, the sign (1: positive or -1: negative) into |pux_num_sign|, and the digits into
2421 the array |pux_nth_digit|. Since the largest |n| is $2^{31}$, n contains at most 10 digits.
2423 @<PUTeX routines...@>=
2424 procedure split_number (n:integer);
2434 repeat pux_nth_digit(k):=n mod 10; n:=n div 10; incr(k);
2437 while k < 10 do begin
2438 pux_nth_digit(k) := 0;
2444 @<scan and split the number@>=
2447 split_number(cur_val);
2450 @ @<scan a CJK number with a possible selector and then split it@>=
2452 scan_int; saved_val:=cur_val;
2453 split_number(cur_val);
2454 if scan_keyword("offset") then begin
2456 digit_base:=cur_val;
2457 if scan_keyword("sign") then begin
2462 sign:=negative_wchar_offset;
2467 @ Using full-width arabic characters to show chinese numbers.
2469 procedure print_cjk_int(@!n:integer;digit_base,sign:integer);
2470 var k:0..9; {index to current digit}
2472 if pux_num_sign = -1 then print_wchar(local_names(sign));
2473 for k:=pux_digit_num-1 downto 0 do
2474 print_wchar(local_names(digit_base+pux_nth_digit(k)));
2477 @ @<using full-width arabic characters to print a CJK number@>=
2478 print_cjk_int(cur_val,C_arabic_digit_offset,negative_wsym_offset)
2480 @ @<print a CJK number with specified format@>=
2481 print_cjk_int(saved_val,digit_base,sign)
2483 @ @<scan a CJK name sequence number@>=
2485 scan_eight_bit_int; saved_val:=cur_val;
2486 if scan_keyword("min") then begin
2487 scan_optional_equals; scan_eight_bit_int;
2491 print_err("Missing 'min' part ("); print("min 0 inserted)");
2494 if scan_keyword("max") then begin
2495 scan_optional_equals; scan_eight_bit_int;
2499 print_err("Missing 'max' part ("); print("max 255 inserted)");
2502 if scan_keyword("offset") then begin
2503 scan_optional_equals; scan_eight_bit_int;
2507 print_err("Missing 'offset' part ("); print("offset 0 inserted)");
2510 if min_val <= saved_val and saved_val <= max_val then
2511 cur_val:=offset+saved_val-min_val
2513 print_err("Number is out of the range ("); print("replaced with the min value)");
2519 @ @<print a CJK name sequence member@>=
2520 print_wchar(local_names(cur_val))
2522 @ A fix\_word is a {\sl scaled integers\/} that are multiples
2523 of $2^{-20}$. In other words, a binary point is assumed to be twenty bit
2524 positions from the right end of a binary computer word.
2525 @d fw_unity == @"100000 {$2^{20}$, represents 1.00000}
2526 @d fw_two == @"200000 {$2^{21}$, represents 2.00000}
2527 @d fw_one_fifth==@"33333 {0.2}
2528 @d convfix(#)== (#)*fw_unity div 1000
2531 @!fixword = integer; {this type is used for fixword (12.20) integers}
2534 @ @<Declare the function called |print_fixword|@>=
2535 procedure print_fixword(@!s:fixword); {prints fixword real, rounded to five
2537 var delta:fixword; {amount of allowable inaccuracy}
2539 begin print_char("-"); negate(s); {print the sign, if negative}
2541 print_int(s div fw_unity); {print the integer part}
2543 s:=10*(s mod fw_unity)+5; delta:=10;
2544 repeat if delta>fw_unity then s:=s+@'200000000-50000; {round the last digit}
2545 print_char("0"+(s div fw_unity)); s:=10*(s mod fw_unity); delta:=delta*10;
2550 @ The function |fw_times_sd| do the multiplication of a fixword and a scaled number.
2551 The value of fixword is assumed between 16 and $-16$.
2552 The function returns the result as a scaled number. (See also Sec. 571, 572 and 600.)
2554 @<Declare the function called |fw_times_sd|@>=
2555 function fw_times_sd (@!x:fixword; @!z:scaled) : scaled;
2556 {compute |f| times |s|}
2558 @!a,@!b,@!c,@!d:eight_bits; {byte variables}
2559 @!alpha:integer;@!beta:1..16;
2560 begin @<Replace |z|...@>;
2561 if x>=0 then a:=x div @'100000000
2562 else begin x:=x+@'10000000000;
2564 a:=(x div @'100000000) + 128;
2566 x:=x mod @'100000000; b:=x div @'200000;
2567 x:=x mod @'200000; c:=x div @'400;
2569 sw:=(((((d*z)div@'400)+(c*z))div@'400)+(b*z))div beta;
2570 if a=0 then fw_times_sd:=sw
2571 else if a=255 then fw_times_sd:=sw-alpha
2572 else fw_times_sd:=unity;
2575 @ @<Put each of \TeX's primitives into the hash table@>=
2576 primitive("PUXchar",pux_char_num,0);
2578 @ @<Cases of |print_cmd_chr|...@>=
2579 pux_char_num: print_esc("PUXchar");
2581 @ @<Give improper hyphenation error for Chinese characters inside@>=
2582 begin print_err("Improper "); print_esc("hyphenation");
2583 @.Improper \\hyphenation...@>
2584 print(" will be flushed");
2585 help2("Hyphenation exceptions can't contain Chinese characters")@/
2586 ("But continue; I'll forgive and forget.");
2591 @ @<Cases of |main_control| that build...@>=
2592 mmode+pux_char_num: begin scan_wchar_num; cur_chr:=cur_val;
2593 print_err("Chinese character is ignored in math mode");
2594 help1("Did you forget putting it into an \hbox?");
2597 mmode+pux_char_given: begin
2598 print_err("Chinese character is ignored in math mode");
2599 help1("Did you forget putting it into an \hbox?");
2603 @ @<Cases of |print_cmd_chr|...@>=
2604 pux_char_given: begin print_esc("PUXchar"); print_hex(chr_code);
2607 @* \[58] All about spaces.
2609 @d is_tail_forbidden(#) == type_code(#) = tail_forbidden
2610 @d is_head_forbidden(#) == type_code(#) = head_forbidden
2611 @d is_head_forbidden_wchar(#) == ((# > 255) and (type_code(#) = head_forbidden))
2612 @d is_punc_wchar(#) == ((# > 255) and (type_code(#) <> 0))
2615 @<Global variables@>=
2616 @!main_cf:internal_cfont_number; {the current chinese font}
2617 @!math_mode_save:-mmode..mmode;
2618 @!prev_main_cf:internal_cfont_number; {the current chinese font}
2619 @!pre_undet_glue_ptr:pointer; {point to the node just before a undetermined glue}
2620 @!undet_glue_ptr:pointer; {point to the undetermined glue}
2621 @!cglue_ptr:pointer;
2622 @!cglue_spec:pointer;
2623 @!pre_glue_char_ptr:pointer;
2624 @!outer_tail:pointer;
2625 @!hbox_tail:pointer;
2626 @!in_set_box:boolean;
2628 @ @<Initialization of global variables done in the |main_control| procedure@>=
2629 pre_undet_glue_ptr:=null;
2630 pre_glue_char_ptr:=null;
2633 @d tail_append_glue(#)==
2634 begin cglue_ptr:=get_node(small_node_size); cglue_spec:=#;
2635 type(cglue_ptr):=glue_node; subtype(cglue_ptr):=normal;
2636 leader_ptr(cglue_ptr):=null; glue_ptr(cglue_ptr):=cglue_spec;
2637 incr(glue_ref_count(cglue_spec));
2638 tail_append(cglue_ptr);
2641 @ Here is the check done before switching to regular character string.
2642 @<If the preceding node is wchar node, then append a cespace@>=
2643 if tail=head then begin
2644 if mode=-hmode then begin {beginning of a restricted hlist}
2645 outer_tail:=nest[nest_ptr-1].tail_field;
2646 if pre_undet_glue_ptr<>null then begin
2647 if outer_tail=link(pre_undet_glue_ptr) and pre_glue_char_ptr<>null
2648 and is_wchar_node(pre_glue_char_ptr) then begin
2649 decr(glue_ref_count(glue_ptr(outer_tail)));
2650 glue_ptr(outer_tail):=cfont_ceglue_spec[prev_main_cf];
2651 incr(glue_ref_count(cfont_ceglue_spec[prev_main_cf]));
2653 pre_undet_glue_ptr:=null;
2657 else if is_char_node(tail) and is_wchar_node(tail) then begin
2658 if is_head_forbidden(cur_chr) then tail_append(new_penalty(inf_penalty));
2659 tail_append_glue(cfont_ceglue_spec[main_cf]);
2661 else if pre_undet_glue_ptr<>null and link(pre_undet_glue_ptr)=tail and
2662 pre_glue_char_ptr<>null and is_wchar_node(pre_glue_char_ptr) then begin
2663 decr(glue_ref_count(glue_ptr(tail)));
2664 glue_ptr(tail):=cfont_ceglue_spec[prev_main_cf];
2665 incr(glue_ref_count(cfont_ceglue_spec[prev_main_cf]));
2667 pre_undet_glue_ptr:=null;
2668 pre_glue_char_ptr:=null;
2671 @ If the next token come after the math shift \$ is a wide character, then
2672 a cespace is appended first.
2673 @<If the token is a wide character, then append a cspace@>=
2674 if cur_cmd=pux_char_num then
2675 begin scan_wchar_num; cur_chr:=cur_val; cur_cmd:=pux_char_given;
2677 if cur_cmd=letter or cur_cmd=other_char or cur_cmd=pux_char_given then
2678 if is_wchar(cur_chr) then
2679 if is_punc_wchar(cur_chr) then begin
2680 if is_head_forbidden(cur_chr) then tail_append(new_penalty(inf_penalty));
2681 tail_append_glue(zero_glue);
2684 tail_append_glue(cfont_ceglue_spec[main_cf])
2688 @<Append double-byte character |cur_chr|...@>=
2690 @<If the current wchar is at the beginning of a restricted hlist that
2691 is after a undetermined spacer, then we have to determine that space.
2692 When it is done |goto save_cur_wchar|@>;
2693 @<If the previous node is an undetermined glue, then make it certain and
2694 |goto save_cur_wchar|@>;
2695 if not is_char_node(tail) then goto save_cur_wchar;
2696 main_loop_wchar+1:@<the previous node is a character node, so we have to append
2699 fast_get_avail(lig_stack);
2700 font(lig_stack):=main_cf;
2701 character(lig_stack):=cur_chr;
2702 tail_append(lig_stack);@/
2703 @<Prepare a nonbreak space if the current wide character is not allowed to
2704 appear at the end of line@>;
2705 fetch_next_tok:get_next; {set only |cur_cmd| and |cur_chr|, for speed}
2706 @<Check the lookahead character@>;
2707 x_token; {now expand and set |cur_cmd|, |cur_chr|, |cur_tok|}
2708 @<Check the lookahead character@>;
2709 if cur_cmd=char_num then
2710 begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given; goto next_is_a_char;
2712 if cur_cmd=pux_char_num then
2713 begin scan_wchar_num; cur_chr:=cur_val;
2714 if is_punc_wchar(cur_chr) then
2715 if is_head_forbidden(cur_chr) then tail_append(new_penalty(inf_penalty));
2716 tail_append_glue(cfont_glue_spec[main_cf]);
2717 goto save_cur_wchar;
2719 {next token is not a character token}
2720 if cur_cmd=math_shift then
2721 if is_punc_wchar(character(lig_stack)) then
2722 tail_append_glue(zero_glue)
2724 tail_append_glue(cfont_ceglue_spec[main_cf]);
2726 next_is_a_char: begin@/
2728 if is_head_forbidden(cur_chr) then tail_append(new_penalty(inf_penalty));
2729 if is_punc_wchar(character(lig_stack)) then
2730 tail_append_glue(zero_glue)
2732 tail_append_glue(cfont_ceglue_spec[main_cf]);
2737 @ @<If the current wchar is at the beginning...@>=
2738 if tail=head then begin {beginning of a restricted hlist}
2739 if mode=-hmode then begin
2740 outer_tail:=nest[nest_ptr-1].tail_field;
2741 if pre_undet_glue_ptr<>null then begin
2742 if outer_tail=link(pre_undet_glue_ptr) then begin
2743 undet_glue_ptr:=outer_tail;
2744 @<Modify the undetermined glue according the type of pre-glue character@>;
2746 pre_undet_glue_ptr:=null;
2749 goto save_cur_wchar;
2753 @ @<Modify the undetermined glue...@>=
2754 decr(glue_ref_count(glue_ptr(undet_glue_ptr)));
2755 if pre_glue_char_ptr<>null and is_wchar_node(pre_glue_char_ptr) then begin
2756 glue_ptr(undet_glue_ptr):=cfont_glue_spec[prev_main_cf];
2757 incr(glue_ref_count(cfont_glue_spec[prev_main_cf]));
2758 pre_glue_char_ptr:=null;
2761 glue_ptr(undet_glue_ptr):=cfont_ceglue_spec[prev_main_cf];
2762 incr(glue_ref_count(cfont_ceglue_spec[prev_main_cf]));
2765 @ @<If the previous node is an undetermined glue...@>=
2766 if pre_undet_glue_ptr<>null then begin
2767 if link(pre_undet_glue_ptr)=tail then begin
2768 undet_glue_ptr:=tail;
2769 @<Modify the undetermined glue according the type of pre-glue character@>;
2770 pre_undet_glue_ptr:=null;
2771 goto save_cur_wchar;
2773 pre_undet_glue_ptr:=null;
2777 @ @<the previous node is a character node...@>=
2778 if is_wchar_node(tail) then begin
2779 if is_head_forbidden_wchar(cur_chr) then
2780 tail_append(new_penalty(inf_penalty));
2781 tail_append(new_glue(cfont_glue_spec[main_cf]));
2783 else begin {previous node is a single byte character}
2784 if is_punc_wchar(cur_chr) then begin
2785 if is_head_forbidden(cur_chr) then tail_append(new_penalty(inf_penalty));
2786 tail_append_glue(zero_glue);
2789 if is_head_forbidden(character(tail)) then tail_append(new_penalty(inf_penalty));
2790 tail_append_glue(cfont_ceglue_spec[main_cf]);
2796 @ For those Chinese puncuations that shoudn't appear in the line end,
2797 we append a penalty node to prevent line boken after it.
2798 @<Prepare a nonbreak space if the current wide...@>=
2799 if is_punc_wchar(cur_chr) then
2800 if is_tail_forbidden(cur_chr) then tail_append(new_penalty(inf_penalty))
2802 @ @<Check the lookahead character@>=
2803 if cur_cmd=letter or cur_cmd=other_char or cur_cmd=pux_char_given or
2804 cur_cmd=char_given then
2805 if is_wchar(cur_chr) then begin
2806 if is_punc_wchar(cur_chr) then
2807 if is_head_forbidden(cur_chr) then tail_append(new_penalty(inf_penalty));
2808 tail_append_glue(cfont_glue_spec[main_cf]);
2809 goto save_cur_wchar;
2811 else goto next_is_a_char
2814 @ @<Look ahead for next character. If it is a wide...@>=
2815 get_next; {set only |cur_cmd| and |cur_chr|, for speed}
2816 if cur_cmd=letter or cur_cmd=other_char then
2817 if is_wchar(cur_chr) then goto main_loop_lookahead+2
2818 else goto main_loop_lookahead+1;
2819 if cur_cmd=char_given then goto main_loop_lookahead+1;
2820 if cur_cmd=pux_char_given then goto main_loop_lookahead+2;
2821 x_token; {now expand and set |cur_cmd|, |cur_chr|, |cur_tok|}
2822 if cur_cmd=letter or cur_cmd=other_char then
2823 if is_wchar(cur_chr) then goto main_loop_lookahead+2
2824 else goto main_loop_lookahead+1;
2825 if cur_cmd=char_given then goto main_loop_lookahead+1;
2826 if cur_cmd=char_num then
2827 begin scan_char_num; cur_chr:=cur_val; goto main_loop_lookahead+1;
2829 if cur_cmd=pux_char_num then
2830 begin scan_wchar_num; cur_chr:=cur_val; goto main_loop_lookahead+2;
2832 if cur_cmd=no_boundary then bchar:=non_char;
2833 main_loop_lookahead+2: cur_r:=bchar; lig_stack:=null; goto main_lig_loop;
2834 main_loop_lookahead+1: adjust_space_factor;
2835 fast_get_avail(lig_stack); font(lig_stack):=main_f;
2836 cur_r:=qi(cur_chr); character(lig_stack):=cur_r;
2837 if cur_r=false_bchar then cur_r:=non_char {this prevents spurious ligatures}
2840 @ @<Cases of |main_control| that handle spacer@>=
2841 hmode+spacer: @<Lookahead and determine the type of spacer to append@>;
2842 hmode+ex_space: @<Lookahead and determine the type of |ex_spacer| to append@>;
2843 mmode+ex_space: begin if pux_xspace=0 then get_x_token; {lookahead}
2844 goto append_normal_space;
2846 hmode+pux_space:@<Handle \PUTeX space command@>;
2847 mmode+pux_space:begin
2848 print_err("This space command is ignored in math mode");
2849 help1("Did you forget putting it into an \hbox?");
2853 @ @<Setup |hbox_tail| and package@>=
2854 if in_set_box then package(0)
2856 if tail<>head and is_char_node(tail) then
2862 if cur_cmd<>spacer then hbox_tail:=null;
2866 @ @<Lookahead and determine the type of spacer to append@>=
2868 if pux_xspace=0 then begin
2869 if tail<>head and is_char_node(tail) then
2870 pre_glue_char_ptr:=tail
2872 pre_glue_char_ptr:=null;
2873 get_x_token; {lookahead}
2874 if cur_cmd=char_num then
2875 begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
2877 else if cur_cmd=pux_char_num then
2878 begin scan_wchar_num; cur_chr:=cur_val; cur_cmd:=pux_char_given;
2880 if cur_cmd=letter or cur_cmd=other_char or cur_cmd=char_given or
2881 cur_cmd=pux_char_given then
2882 if is_wchar(cur_chr) then begin
2884 if pre_glue_char_ptr<>null then goto main_loop_wchar+1;
2885 if hbox_tail<>null and is_wchar_node(hbox_tail) then begin
2886 tail_append_glue(cfont_glue_spec[main_cf]);
2890 tail_append_glue(cfont_ceglue_spec[main_cf]);
2891 if is_punc_wchar(cur_chr) then
2892 if is_head_forbidden(cur_chr) then tail_append(new_penalty(inf_penalty));
2893 if hbox_tail<>null then hbox_tail:= null;
2895 goto save_cur_wchar;
2897 else if (pre_glue_char_ptr<>null and is_wchar_node(tail))
2898 or (hbox_tail<>null and is_wchar_node(hbox_tail)) then begin
2899 tail_append_glue(cfont_ceglue_spec[cur_cfont]);
2903 prev_main_cf:=cur_cfont;
2904 pre_undet_glue_ptr:=tail;
2905 if pre_glue_char_ptr<>null and is_wchar_node(pre_glue_char_ptr) then begin
2906 tail_append_glue(cfont_ceglue_spec[cur_cfont]);
2910 if space_factor=1000 then goto append_normal_space
2911 else begin app_space;
2912 if pux_xspace=0 then goto reswitch else goto big_switch;
2916 @ @<Lookahead and determine the type of |ex_spacer| to append@>=
2918 if pux_xspace=0 then begin
2919 get_x_token; {lookahead}
2920 if cur_cmd=char_num then
2921 begin scan_char_num; cur_chr:=cur_val; cur_cmd:=char_given;
2923 if cur_cmd=pux_char_num then
2924 begin scan_wchar_num; cur_chr:=cur_val; cur_cmd:=pux_char_given;
2926 if cur_cmd=letter or cur_cmd=other_char or cur_cmd=char_given or cur_cmd=pux_char_given then
2927 if is_wchar(cur_chr) then begin
2929 if tail<>head and is_char_node(tail) then
2930 if is_wchar_node(tail) then
2931 goto append_normal_space
2933 goto main_loop_wchar+1;
2934 tail_append_glue(cfont_glue_spec[main_cf]);
2935 goto save_cur_wchar;
2937 else if tail<>head and is_char_node(tail) then
2938 if is_wchar_node(tail) then begin
2939 tail_append_glue(cfont_ceglue_spec[cur_cfont]);
2942 if tail<>head and is_char_node(tail) then
2943 if is_wchar_node(tail) then begin
2944 tail_append_glue(cfont_glue_spec[cur_cfont]);
2947 prev_main_cf:=cur_cfont;
2948 pre_undet_glue_ptr:=tail;
2950 goto append_normal_space;
2955 @d pux_exspace_code=1
2956 @d pux_cspace_code=2
2957 @d pux_cespace_code=3
2958 @<Put each of \TeX's primitives into the hash table@>=
2959 primitive("PUXspace",pux_space,pux_space_code);
2960 primitive("PUXexspace",pux_space,pux_exspace_code);
2961 primitive("PUXcspace",pux_space,pux_cspace_code);
2962 primitive("PUXcespace",pux_space,pux_cespace_code);
2964 @ @<Cases of |print_cmd_chr|...@>=
2965 pux_space: case chr_code of
2966 pux_space_code: print_esc("PUXspace");
2967 pux_exspace_code: print_esc("PUXexspace");
2968 pux_cspace_code: print_esc("PUXcspace");
2969 othercases print_esc("PUXcespace")
2972 @ @<Handle \PUTeX space command@>=
2974 pux_space_code: begin get_x_token;
2975 if space_factor=1000 then goto append_normal_space;
2977 if pux_xspace=0 then goto reswitch else goto big_switch;
2979 pux_exspace_code: begin get_x_token; goto append_normal_space;
2981 pux_cspace_code: tail_append(new_glue(cfont_glue_spec[cur_cfont]));
2982 othercases tail_append(new_glue(cfont_ceglue_spec[cur_cfont]))
2985 @* \[59] CJK font face definition table.
2987 @ @<Put each of \TeX's primitives into the hash table@>=
2988 primitive("PUXcfacedef",pux_cface_def,0);
2990 @ @<Cases of |print_cmd_chr|...@>=
2991 pux_cface_def: print_esc("PUXcfacedef"); {TCW}
2994 pux_cface_def: new_cface(a);
2998 @!cface_base=0; {CJK font face base}
2999 @!null_cface=0; {null CJK font faces}
3003 @!internal_cface_number=cface_base..max_cface;
3005 @ The CJK font face definition table is implemented by parallel arrays as follows.
3007 @d italic=@"40 {bit 6: italic flag}
3008 @d underline=@"20 {bit 5: underline flag}
3009 @d strikeout=@"10 {bit 4: strikeout flag}
3010 @d inverse=@"08 {bit 3: inverse flag}
3011 @d rotated=@"01 {bit 0: rotation flag}
3012 @d default_cface_weight==400
3013 @d default_cface_style=regular
3014 @d default_cface_fw_width==fw_unity
3015 @d default_cface_fw_height==fw_unity
3016 @d cface_id_text(#)==text(cface_id_base+#)
3018 @<Global variables@>=
3019 @!cface_ptr:internal_cface_number;
3020 {index of the first unused entry}
3021 @!cface:array[internal_cface_number] of str_number;
3022 {CJK font face identifier}
3023 @!cface_name:array[internal_cface_number] of str_number;
3024 {CJK font face name}
3025 @!cface_charset:array[internal_cface_number] of eight_bits;
3027 @!cface_weight:array[internal_cface_number] of 1..1000;
3029 @!cface_style:array[internal_cface_number] of eight_bits;
3031 @!cface_fw_width:array[internal_cface_number] of fixword;
3032 {CJK font width ratio}
3033 @!cface_fw_height:array[internal_cface_number] of fixword;
3034 {CJK font heigh ratio}
3035 @!cface_fw_depth:array[internal_cface_number] of fixword;
3036 {CJK font depth ratio}
3037 @!cface_csp_width:array[internal_cface_number] of integer;
3038 {CJK font c-space width}
3039 @!cface_csp_shrink:array[internal_cface_number] of integer;
3040 {CJK font c-space shrink}
3041 @!cface_csp_stretch:array[internal_cface_number] of integer;
3042 {CJK font c-space stretch}
3043 @!cface_cesp_width:array[internal_cface_number] of integer;
3044 {CJK font ce-space width}
3045 @!cface_cesp_shrink:array[internal_cface_number] of integer;
3046 {CJK font ce-space shrink}
3047 @!cface_cesp_stretch:array[internal_cface_number] of integer;
3048 {CJK font ce-space stretch}
3049 @!cface_fw_default_depth:fixword;
3052 @ @<Put each of \TeX's primitives into the hash table@>=
3053 primitive("PUXsetdefaultcface",pux_set_default_cface,int_base+pux_default_cface_code);
3055 @ @<Cases of |print_cmd_chr|...@>=
3056 pux_set_default_cface: print_esc("PUXsetdefaultcface"); {TCW}
3059 pux_set_default_cface: begin p:=cur_chr;
3060 @<Get the next non-blank non-call token@>;
3061 if cur_cmd = pux_set_cface then
3062 word_define(p,cur_chr)
3064 print_err("Here should put a CJK font face command. ");
3065 print("The dafault CJK font face remains unchanged");
3071 @ @<PUTeX routines that will be used by TeX routines@>=
3072 procedure reset_cface_cspace (face_num:integer);
3074 cface_csp_width[face_num]:=g_cspace_width;@/
3075 cface_csp_shrink[face_num]:=g_cspace_shrink;@/
3076 cface_csp_stretch[face_num]:=g_cspace_stretch;@/
3079 @ @<PUTeX routines that will be used by TeX routines@>=
3080 procedure reset_cface_cespace (face_num:integer);
3082 cface_cesp_width[face_num]:=g_cespace_width;@/
3083 cface_cesp_shrink[face_num]:=g_cespace_shrink;@/
3084 cface_cesp_stretch[face_num]:=g_cespace_stretch;@/
3087 @ Setup default and null CJK font faces.
3088 @<Initialize table...@>=
3089 cur_cface:=null_cface; eq_type(cur_cface_loc):=data;
3090 eq_level(cur_cface_loc):=level_one;@/
3091 cface_fw_default_depth:=convfix(puxg_cface_depth);
3092 cface_ptr:=cface_base+1;
3094 cface[null_cface]:="nullcface";@/
3095 cface_name[null_cface]:="nullcjkface";@/
3096 cface_charset[null_cface]:=0;@/
3097 cface_weight[null_cface]:=400; {normal weight}@/
3098 cface_style[null_cface]:=0;@/
3099 cface_fw_width[null_cface]:=0;@/
3100 cface_fw_height[null_cface]:=0;@/
3101 cface_fw_depth[null_cface]:=0;@/
3102 reset_cface_cspace(null_cface);@/
3103 reset_cface_cespace(null_cface);@/
3105 @ The function |find_cface_num| searches the CJK font face definition table
3106 for the entry with the same identifier as |id|. The entry index is return if found;
3107 otherwise, the current value of |cface_ptr| is return.
3109 @d cface_found(#)==((#)<cface_ptr)
3111 @<Declare the function called |find_cface_num|@>=
3112 function find_cface_num(id:str_number):internal_cface_number;
3114 var f:internal_cface_number; {runs through existing faces}
3117 while (f < cface_ptr) do
3119 if str_eq_str(id, cface[f]) then goto done;
3122 done:find_cface_num:=f;
3125 @ @<Declare subprocedures for |prefixed_command|@>=
3126 @<Declare the function called |print_fixword|@>@;
3127 procedure new_cface(@!a:small_number);
3128 label done, done1, common_ending;
3129 var u:pointer; {user's chinese face identifier}
3130 @!t:str_number; {name for the frozen font identifier}
3131 @!id:str_number; {CJK font face identifier}
3132 @!face_name:str_number; {CJK font face name}
3133 @!charset:integer; {CJK font charset}
3134 @!weight:integer; {CJK font weight}
3135 @!style:integer; {CJK font style}
3136 @!w:integer; {CJK font width ratio}
3137 @!h:integer; {CJK font height ratio}
3138 @!d:integer; {CJK font depth ratio}
3139 @!fix_w:fixword; {CJK font width ratio}
3140 @!fix_h:fixword; {CJK font height ratio}
3141 @!fix_d:fixword; {CJK font depth ratio}
3142 @!f:internal_cface_number; {runs through existing faces}
3144 @<Other variables used by |new_cface|@>@;
3145 begin if job_name=0 then open_log_file;
3146 {avoid confusing \.{texput} with the font name}
3147 get_r_token; u:=cur_cs;
3148 if u>=hash_base then t:=text(u)
3149 else if u>=single_base then
3150 if u=null_cs then t:="CFACE"@+else t:=u-single_base
3151 else begin old_setting:=selector; selector:=new_string;
3152 print("CFACE"); print(u-active_base); selector:=old_setting;
3153 str_room(1); t:=make_string;
3155 define(u,pux_set_cface,null_cface);
3156 scan_optional_equals;
3157 @<Setup variables before scanning CJK font face parameters@>;
3158 @<Scan CJK font face identifier@>;
3159 @<Scan CJK font face name@>;
3160 @<Scan optional CJK font face definition parameters@>;
3161 @<If the face name is missing, then ignore this face deinition@>;
3162 @<If this Chinese face has already been loaded, then |goto common_ending|@>;
3163 @<Setup this new Chinese face@>;
3164 common_ending: equiv(u):=f; eqtb[cface_id_base+f]:=eqtb[u]; cface_id_text(f):=t;
3167 @ @<Setup variables before scanning CJK font face parameters@>=
3168 charset:=pux_charset; {set to the base charset of document}
3169 w:=1000; h:=1000; d:=puxg_cface_depth; @/
3170 weight:=400; {normal weight}@/
3171 style:=0; {regular style}
3172 if puxg_rotate_ctext<>0 then style:=style+rotated;
3176 @ @<Scan CJK font face identifier@>=
3180 f:=find_cface_num(id);
3181 if (f < cface_ptr) then
3183 flush_string; id:=cface[f]; {for saving string pool sapce}
3185 print_err("The Chinese face id ("); print(id);
3186 print(") is already used"); error;
3191 print_err("Missing CJK font face identifier"); error;
3194 @ @<Scan CJK font face name@>=
3196 face_name:=scan_name;
3197 if face_name > 0 then
3200 while (k < cface_ptr) do
3202 if str_eq_str(face_name, cface_name[k]) then
3205 face_name:=cface_name[k]; f:=k;
3213 print_err("Missing CJK font face name"); error;
3214 face_name:=cface_name[null_cface];
3219 @ @<Other variables used by |new_cface|@>=
3220 @!i_flag:boolean; {italic flag}
3221 @!u_flag:boolean; {underline flag}
3222 @!s_flag:boolean; {strikeout flag}
3223 @!r_flag:boolean; {rotation flag}
3224 @!v_flag:boolean; {inverse flag}
3225 @!more_param:boolean; {have more parameters to come}
3227 @ @<Scan optional CJK font face definition parameters@>=
3228 i_flag:=false; u_flag:=false; s_flag:=false;@/
3229 r_flag:=false; v_flag:=false;@/
3233 @<Get the next non-blank non-call token@>;
3234 if cur_cmd=letter then
3236 'c','C': @<Scan the CJK font charset@>;
3237 'w','W': @<Scan the CJK font width@>;
3238 'h','H': @<Scan the CJK font height@>;
3239 'd','D': @<Scan the CJK font depth@>;
3240 't','T': @<Scan the CJK font weight@>;
3241 's','S': @<Scan the CJK font style@>;
3242 othercases more_param:=false;
3244 else more_param:=false;
3250 @<Scan the CJK font charset@>=
3251 begin scan_optional_equals;@/
3253 if (cur_val<0)or(cur_val>255) then
3254 begin print_err("Improper `charset' value (");
3255 print_int(charset); print("), replaced by default charset");
3256 help2("I can only handle nonnegative charset value up to 255,")@/
3257 ("so I've changed what you said to default charset.");
3265 @<Scan the CJK font width@>=
3266 begin scan_optional_equals;@/
3267 scan_int; w:=cur_val;
3268 if (w<=0)or(w>1000) then
3269 begin print_err("Improper `width' value (");
3270 print_int(w); print("), replaced by 1000");
3271 help2("I can only handle fonts at positive width ratio that are less")@/
3272 ("than or equal to 1000, so I've changed what you said to 1000.");
3277 @ @<Scan the CJK font height@>=
3278 begin scan_optional_equals;@/
3279 scan_int; h:=cur_val;
3280 if (h<=0)or(h>1000) then
3281 begin print_err("Improper `height value (");
3282 print_int(h); print("), replaced by 1000");
3283 help2("I can only handle fonts at positive height ratio that are less")@/
3284 ("than or equal to 1000, so I've changed what you said to 1000.");
3289 @ @<Scan the CJK font depth@>=
3290 begin scan_optional_equals;@/
3291 scan_int; d:=cur_val;
3292 if (d<0)or(d>1000) then
3293 begin print_err("Improper `depth' value (");
3294 print_int(d); print("), replaced by 0.2");
3295 help3("I can only handle fonts at nonegative depth ratio that are less")@/
3296 ("than or equal to 1000, so I've changed what you said to")@/
3297 ("the current \puxgCfaceDepth value.");
3298 error; d:=puxg_cface_depth;
3302 @ @<Scan the CJK font weight@>=
3303 begin scan_optional_equals;@/
3304 scan_int; weight:=cur_val;
3305 if (weight < 0) or (weight > 1000) then
3306 begin print_err("Illegal CJK font weight has been changed to 400");@/
3307 help1("The font weight must be between 1 and 1000.");
3308 int_error(cur_val); weight:=400; {normal weight}
3313 @<Scan the CJK font style@>=
3314 begin scan_optional_equals;@/
3315 @<Get the next non-blank non-call token@>;
3316 if cur_cmd=letter then
3318 "i", "I": if not i_flag then begin style:=style+italic; i_flag:=true; end;
3319 "u", "U": if not u_flag then begin style:=style+underline; u_flag:=true; end;
3320 "s", "S": if not s_flag then begin style:=style+strikeout; s_flag:=true; end;
3321 "r", "R": if not r_flag then @<Set CJK font rotation style@>;
3322 "v", "V": if not v_flag then begin style:=style+inverse; v_flag:=true; end;
3324 begin print_err("Illegal CJK font style setting has been ignored");@/
3325 print(" ("); print(cur_chr); print(")"); back_error;
3326 {fix the case when cur\_chr is a double-byte char}
3327 help2("The CJK font style setting should use characters:")@/
3328 ("i:italic, u:underline, s:strikeout, r:rotated, v:reversed");
3333 @ @<Set CJK font rotation style@>=
3335 if puxg_rotate_ctext<>0 then
3336 style:=style-rotated
3338 style:=style+rotated;
3342 @ @<If the face name is missing, then ignore this face deinition@>=
3343 if f=null_cface then
3347 @ @<If this Chinese face has...@>=
3351 if f <> null_cface then
3352 if weight=cface_weight[f] and style=cface_style[f] then
3353 if fix_w=cface_fw_width[f] and fix_h=cface_fw_height[f] and fix_d=cface_fw_depth[f] then@/
3357 @<Setup this new Chinese face@>=
3358 if cface_ptr <= max_cface then
3362 cface_name[f]:=face_name;@/
3363 cface_charset[f]:=charset;@/
3364 cface_weight[f]:=weight;@/
3365 cface_style[f]:=style;@/
3366 if style mod 2 = 1 then begin
3367 cface_fw_width[f]:=fix_w; cface_fw_height[f]:=fix_h;
3370 cface_fw_width[f]:=fix_h; cface_fw_height[f]:=fix_w;
3372 cface_fw_depth[f]:=fix_d;@/
3373 reset_cface_cspace(f);@/
3374 reset_cface_cespace(f);@/
3379 print_err("CJK font Face definition table overflow"); error;
3382 @* \[59] CJK font definition table.
3385 @!cfont_base=font_max_limit+1; {CJK font base}
3386 @!cfont_max=font_max_limit+1+cfont_max_limit; {maximum internal chinese font number}
3390 @!internal_cfont_number=cfont_base..cfont_max;
3392 @ @<Initialize table entries...@>=
3393 cur_cfont:=default_cfont; eq_type(cur_cfont_loc):=data;
3394 eq_level(cur_cfont_loc):=level_one;@/
3396 @ @<Global variables@>=
3397 @!cfont_ptr:internal_cfont_number;
3398 @!cfont_face:array[internal_cfont_number] of internal_cface_number;
3399 {CJK font face name}
3400 @!cfont_dsize:array[internal_cfont_number] of scaled;
3401 {CJK font design size}
3402 @!cfont_size:array[internal_cfont_number] of scaled;
3404 @!cfont_width:array[internal_cfont_number] of scaled;
3406 @!cfont_height:array[internal_cfont_number] of scaled;
3408 @!cfont_depth:array[internal_cfont_number] of scaled;
3410 @!cfont_glue_spec:array[internal_cfont_number] of pointer;
3411 {CJK font inter-character space}
3412 @!cfont_ceglue_spec:array[internal_cfont_number] of pointer;
3413 {CJK font inter-character space}
3414 @!cfont_used:array[internal_cfont_number] of boolean;
3415 {has a character from this chinese font actually appeared in the output?}
3419 for k:=cfont_base to cfont_max do cfont_used[k]:=false;
3420 cfont_face[null_cfont]:=null_cface;
3421 cfont_dsize[null_cfont]:=0;
3422 cfont_size[null_cfont]:=0;
3423 cfont_width[null_cfont]:=0;
3424 cfont_height[null_cfont]:=0;
3425 cfont_depth[null_cfont]:=0;
3427 @ @<Initialize table entries...@>=
3428 cfont_ptr:=default_cfont;
3430 @ @<Declare PUTeX subprocedures for |prefixed_command|@>=
3431 procedure set_cglue_spec(n:integer);
3432 var cface_num:integer;
3434 cface_num:=cfont_face[n];
3435 width(cfont_glue_spec[n]):=xn_over_d(cfont_size[n], cface_csp_width[cface_num], 1000);
3436 shrink(cfont_glue_spec[n]):=xn_over_d(cfont_size[n], cface_csp_shrink[cface_num], 1000);
3437 stretch(cfont_glue_spec[n]):=xn_over_d(cfont_size[n], cface_csp_stretch[cface_num], 1000);
3440 @ @<Declare PUTeX subprocedures for |prefixed_command|@>=
3441 procedure set_ceglue_spec(n:integer);
3442 var cface_num:integer;
3444 cface_num:=cfont_face[n];
3445 width(cfont_ceglue_spec[n]):=xn_over_d(cfont_size[n], cface_cesp_width[cface_num], 1000);
3446 shrink(cfont_ceglue_spec[n]):=xn_over_d(cfont_size[n], cface_cesp_shrink[cface_num], 1000);
3447 stretch(cfont_ceglue_spec[n]):=xn_over_d(cfont_size[n], cface_cesp_stretch[cface_num], 1000);
3451 @ @<Initialization of global variables done in the |main_control| procedure@>=
3452 cfont_glue_spec[null_cfont]:=new_spec(zero_glue);
3453 cfont_ceglue_spec[null_cfont]:=new_spec(zero_glue);
3455 @ @<Other local variables used by procedure |new_font|@>=
3456 @!face_id:str_number; {Chinese face name fetched from |\\font| command}
3457 @!jj:internal_cface_number;
3458 @!cface_num:internal_cface_number;
3464 @<Define a CJK font and then goto |common_ending|@>=
3466 define(u, set_cfont, null_cfont);
3467 cface_num:=pux_default_cface;@/
3468 @<Fetch the Chinese face name@>;
3469 @<Fetch the font design size and compute font 'at' size@>;
3470 @<If this CJK font has already been loaded, set |f| to the internal
3471 CJK font number and |goto| common\_ending@>;
3472 f:=make_cfont(cface_num,dsize,size);@/
3477 @d is_letter(#)==((#>='A' and #<='Z') or (#>='a' and #<='z'))
3478 @<Fetch the Chinese face name@>=
3480 j:=j+5; {skip the prefix 'CFONT'}
3481 while is_letter(str_pool[j]) do {fixme for wchar}
3483 append_char(str_pool[j]);
3486 if pool_ptr <> str_start[str_ptr] then
3488 face_id:=make_string;@/
3489 cface_num:=find_cface_num(face_id);
3494 print_err("Missing Chinese face identifier"); error;
3498 @d is_digit(#)==(# >= '0' and # <= '9')
3499 @<Fetch the font design size and compute font 'at' size@>=
3501 while is_digit(str_pool[j]) do
3503 ds:= ds*10+(str_pool[j]-'0');
3508 print_err("Missing CJK font size specification, replaced by 10pt");
3509 ds:=10; {set to default size: 10pt}
3512 dsize:=mult_integers(ds,unity);
3516 if s>=0 then size:=s
3517 else size:=xn_over_d(dsize, -s, 1000);
3520 @d defined_cfont(#)==(#)<cfont_ptr
3521 @d undefined_cfont(#)==(#)=cfont_ptr
3523 @<Declare the procedure called |check_cfont|@>=
3524 function check_cfont(@!cface_num:internal_cface_number;@!size:scaled):internal_cfont_number;
3526 var f:internal_cfont_number;
3529 while (f<cfont_ptr) do
3531 if cface_num=cfont_face[f] and size=cfont_size[f] then goto done;
3534 done:check_cfont:=f;
3537 @ @<If this CJK font has already been...@>=
3538 f:=check_cfont(cface_num,size);
3539 if defined_cfont(f) then goto common_ending;
3543 @<Declare the procedure called |make_cfont|@>=
3544 function make_cfont(cfn:internal_cface_number; dsize, size:scaled):internal_cfont_number;
3546 if cfont_ptr <= cfont_max then
3548 cfont_face[cfont_ptr]:=cfn;@/
3549 cfont_dsize[cfont_ptr]:=dsize;@/
3550 cfont_size[cfont_ptr]:=size;@/
3551 cfont_width[cfont_ptr]:=fw_times_sd(cface_fw_width[cfn], size);@/
3552 cfont_height[cfont_ptr]:=fw_times_sd(cface_fw_height[cfn], size);@/
3553 cfont_depth[cfont_ptr]:=fw_times_sd(cface_fw_depth[cfn], size);@/
3554 cfont_glue_spec[cfont_ptr]:=new_spec(zero_glue);
3555 set_cglue_spec(cfont_ptr);
3556 cfont_ceglue_spec[cfont_ptr]:=new_spec(zero_glue);
3557 set_ceglue_spec(cfont_ptr);
3558 make_cfont:=cfont_ptr;@/
3563 print_err("CJK font table overflow"); error;
3568 @ @<Cases of |print_cmd_chr|...@>=
3569 set_cfont:begin print("select CJK font "); slow_print(cface[cfont_face[chr_code]]);
3570 print(" at ("); print_scaled(cfont_size[chr_code]); print("pt"); print(")");
3573 @* \[57] Matching faces.
3578 @!internal_ectbl_number=min_ectbl..max_ectbl;
3581 @ @<Global variables@>=
3582 @!ectbl_eface_name:array[internal_ectbl_number] of str_number;
3583 {the table of English face names }
3584 @!ectbl_ptr:internal_ectbl_number;
3585 {index to the first unused entry}
3587 @ |ectbl_cface_num| table entries are already initialized in section 232.
3589 @<Initialize table entries...@>=
3590 ectbl_ptr:=min_ectbl;
3591 equiv(ectbl_cface_num_base):=null_cface;
3592 eq_type(ectbl_cface_num_base):=data;
3593 eq_level(ectbl_cface_num_base):=level_one;
3594 for k:=ectbl_cface_num_base+1 to font_matching_table_base-1 do
3595 eqtb[k]:=eqtb[ectbl_cface_num_base];
3598 @ @<Put each of \TeX's primitives into the hash table@>=
3599 primitive("PUXfacematch",pux_face_match,0);
3601 @ @<Cases of |print_cmd_chr|...@>=
3602 pux_face_match: print_esc("PUXfacematch");
3605 pux_face_match: match_ec_face(a);
3608 @ The function |find_ec_num| lookup the |ectbl_eface_name| table
3609 for the name |eface_name|. It returns the index to the name if the name
3610 exits; otherwose, it returns the current value of |ectbl_ptr|.
3612 @d ectbl_found(#)==((#)<ectbl_ptr)
3614 @<Declare the function called |find_ec_num|@>=
3615 function find_ec_num(eface_name:str_number):internal_ectbl_number;
3620 while k < ectbl_ptr do
3622 if str_eq_str(eface_name,ectbl_eface_name[k]) then goto done;
3625 done: find_ec_num:=k;
3629 @<Declare subprocedures for |prefixed_command|@>=
3630 procedure make_cfont_id (f:internal_cfont_number; a:small_number);
3638 buffer[buf_size+1]:='C';
3639 buffer[buf_size+2]:='F';
3640 buffer[buf_size+3]:='O';
3641 buffer[buf_size+4]:='N';
3642 buffer[buf_size+5]:='T';
3645 repeat dig[i]:=n mod 10; n:=n div 10; incr(i);
3647 while i>0 do {append design size}
3649 buffer[m]:="0"+dig[i];
3652 no_new_control_sequence:=false;
3653 u:=id_lookup(buf_size+1,m-buf_size-1);
3654 no_new_control_sequence:=true;
3656 define(u,set_cfont,f); eqtb[font_id_base+f]:=eqtb[u]; font_id_text(f):=t;
3659 @ @<Declare PUTeX subprocedures for |prefixed_command|@>=
3660 function fetch_efont_face (@!efont_name:str_number):str_number;
3665 p:=str_start[efont_name+1]-1; {last char position of efont\_name}@/
3666 while is_digit(str_pool[p]) do decr(p); {assumed that the TeX font name has letters}
3667 k:=str_start[efont_name];
3670 append_char(str_pool[k]);
3674 fetch_efont_face:=s;
3679 @<Declare subprocedures for |prefixed_command|@>=
3680 @<Declare the function called |find_ec_num|@>@;
3681 procedure match_ec_face(@!a:small_number);
3682 label done1, done2, exit;
3684 @!eface_name, @!efname, @!efont_name, @!cface_id:str_number;
3685 @!cfont_num:internal_cfont_number;
3686 @!cface_num:internal_cface_number;
3689 err:=false; f:=ectbl_ptr;@/
3690 eface_name:=scan_name;
3691 if cur_cmd=pux_set_cface then
3692 eface_name:=fetch_efont_face(font_name[cur_font]) {should be flushed later}
3693 else if eface_name=0 then begin
3694 print_err("Missing a TeX face name");
3697 f:=find_ec_num(eface_name);
3698 if ectbl_found(f) then begin {it is already in the |ectbl_eface_name| table}
3700 eface_name:=ectbl_eface_name[f]
3702 if cur_cmd=pux_set_cface then begin {the second form: match face of current efont}
3704 @<Define the |cur_cfont| according to |cur_font| and |cface_num|@>;
3707 @<Fetch a Chinese face id@>;
3708 @<Add this face matching@>;
3711 @ @<Define the |cur_cfont| according to |cur_font| and |cface_num|@>=
3712 cfont_num:=check_cfont(cface_num, font_size[cur_font]);
3713 if undefined_cfont(cfont_num) then begin
3714 cfont_num:=make_cfont(cface_num,font_dsize[cur_font],font_size[cur_font]);
3715 make_cfont_id(cfont_num,a);
3717 define(cur_cfont_loc,data,cfont_num)
3721 @ @<Fetch a Chinese face id@>=
3723 @<Get the next non-blank non-call token@>;
3724 if cur_cmd=pux_set_cface then
3727 print_err("Missing a CJK font face identifier");
3729 cface_num:=pux_default_cface;
3733 @ @<Add this face matching@>=
3734 if f > max_ectbl then begin
3735 print_err("Font face matching table overflow");
3739 if not err then begin
3740 define(ectbl_cface_num_base+f,data,cface_num);
3741 if f = ectbl_ptr then begin {add this new eface name the the |eface_name table|}
3742 ectbl_eface_name[f]:=eface_name;
3747 @ @<Declare subprocedures for |prefixed_command|@>=
3748 function lookup_cface (@!efont_name: str_number) : internal_cface_number;
3750 @!cface_num:internal_cface_number;@/
3751 @!eface_name:str_number;@/
3753 eface_name:=fetch_efont_face(efont_name);
3754 k:=find_ec_num(eface_name);
3756 if ectbl_found(k) then
3757 cface_num:=ectbl_cface_num(k)
3758 else cface_num:=pux_default_cface;
3759 lookup_cface:=cface_num;
3763 @* \[60] Font matching.
3765 @ @<Initialize table entries...@>=
3766 equiv(font_matching_table_base):=null_cfont;
3767 eq_type(font_matching_table_base):=data;
3768 eq_level(font_matching_table_base):=level_one;
3769 for k:=font_matching_table_base+1 to math_font_base-1 do
3770 eqtb[k]:=eqtb[font_matching_table_base];
3772 @ @<Put each of \TeX's primitives into the hash table@>=
3773 primitive("PUXfontmatch",pux_font_match,0);
3777 pux_font_match: match_ec_font(a);
3779 @ @<Declare subprocedures for |prefixed_command|@>=
3780 procedure match_ec_font(@!a:small_number);
3782 var efont_num:internal_font_number;
3783 @!cfont_num:internal_cfont_number;
3784 @!cface_num:internal_cface_number;
3786 @<Get the next non-blank non-call token@>;
3787 if cur_cmd = pux_set_cface then {the first form}
3789 efont_num:=cur_font;
3791 @<Define the |cur_cfont| according to |cur_font| and |cface_num|@>;
3794 if cur_cmd = set_font then {the second form}
3797 print_err("Missing Tex font identifier");
3798 help2("I was looking for a control sequence whose")@/
3799 ("current meaning has been defined by \font.");
3800 back_error; efont_num:=null_font;
3802 @<Get the next non-blank non-call token@>;
3803 if cur_cmd = set_cfont then cfont_num:=cur_chr
3805 print_err("Missing CJK font identifier");
3806 help2("I was looking for a control sequence whose")@/
3807 ("current meaning has been defined by \cfont.");
3808 back_error; cfont_num:=null_cfont;
3811 if efont_num<>null_font and cfont_num<>null_cfont then
3812 define(font_matching_table_base+efont_num-font_base,data,cfont_num);
3815 @ @<Other variables used by the procedure |prefixed_command|@>=
3816 @!cface_num:internal_cface_number;
3817 @!cfont_num:internal_cfont_number;
3819 @ @<Set the matching CJK font@>=
3820 cfont_num:=font_matching_table(cur_chr);
3821 if cfont_num=null_cfont then begin {efont not mapped}
3822 if cur_cface=null_cface then
3823 cface_num:=lookup_cface(font_name[cur_chr])
3824 else cface_num:=cur_cface;
3825 @<Build a CJK font according to |cur_chr| and |cface_num| if it is not exist@>;
3828 if cur_cface<>null_cface and cfont_face[cfont_num]<>cur_cface then begin
3829 cface_num:=cur_cface;
3830 @<Build a CJK font according to |cur_chr| and |cface_num| if it is not exist@>;
3832 define(cur_cfont_loc,data,cfont_num)
3834 @ @<Build a CJK font according to |cur_chr| and |cface_num| if it is not exist@>=
3835 cfont_num:=check_cfont(cface_num, font_size[cur_chr]);
3836 if undefined_cfont(cfont_num) then begin
3837 cfont_num:=make_cfont(cface_num,font_dsize[cur_chr],font_size[cur_chr]);
3838 make_cfont_id(cfont_num,a);
3842 set_cfont: define(cur_cfont_loc,data,cur_chr);
3844 @ @<Other variables used by the procedure |prefixed_command|@>=
3845 cface_id:str_number;
3848 pux_set_cface: begin
3850 if cface_num <> cfont_face[cur_cfont] then begin
3851 @<Define the |cur_cfont| according to |cur_font| and |cface_num|@>;
3853 define(cur_cface_loc,data,cface_num);
3856 @ @<Put each of \TeX's primitives into the hash table@>=
3857 primitive("puxgRotateCtext",puxg_assign_flag,int_base+puxg_rotate_ctext_code);
3858 primitive("puxXspace",puxg_assign_int,int_base+pux_xspace_code);
3859 primitive("puxCJKcharOther",puxg_assign_int,int_base+pux_wcharother_code);
3860 primitive("puxCJKinput",puxg_assign_int,int_base+pux_CJKinput_code);
3861 primitive("puxCharSet",puxg_assign_int,int_base+pux_charset_code);
3862 primitive("puxgCfaceDepth",puxg_assign_int,int_base+puxg_cface_depth_code);
3865 @ @<Cases of |print_cmd_chr|...@>=
3867 if chr_code=puxg_rotate_ctext_code+int_base then
3868 print_esc("puxgRotateCtext");
3870 if chr_code=pux_xspace_code+int_base then
3871 print_esc("puxXspace")
3872 else if chr_code=pux_wcharother_code+int_base then
3873 print_esc("puxCJKcharOther")
3874 else if chr_code=pux_CJKinput_code+int_base then
3875 print_esc("puxCJKinput")
3876 else if chr_code=pux_charset_code+int_base then
3877 print_esc("puxCharSet")
3878 else if chr_code=puxg_cface_depth_code+int_base then
3879 print_esc("puxgCfaceDepth");
3882 puxg_assign_flag: begin p:=cur_chr; scan_optional_equals; scan_int;
3883 if cur_val=0 and eqtb[p].int<>0 then begin
3884 print_err("Reset a PUTeX global parameter is not allowed here");
3885 help2("If a PUTeX global parameter was set to be a nonzero value,")@/
3886 ("it can't be reset to be zero again");
3890 if p=puxg_rotate_ctext_code+int_base then
3891 @<Handle the command |puxgRotateCtext|@>;
3892 word_define(p,cur_val);
3896 @ @<Handle the command |puxgRotateCtext|@>=
3897 if puxg_rotate_ctext=0 and cur_val<>0 then begin
3899 while n < cface_ptr do begin
3900 if cface_style[n] mod 2 = 1 then
3901 cface_style[n]:=cface_style[n]-rotated
3903 cface_style[n]:=cface_style[n]+rotated;
3909 puxg_assign_int: begin p:=cur_chr; q:=p-int_base;
3910 scan_optional_equals; scan_int;
3911 if cur_val < 0 then begin
3912 print_err("Negative "); print_param(p-int_base);
3913 print(" value ("); print_int(cur_val); print("), it remains unchanged");
3914 help1("This PUTeX parameter can't be negative.");
3917 else if q=pux_charset_code and cur_val > 255 then begin
3918 print_err("Too large "); print_param(q);
3919 print(" value ("); print_int(cur_val); print("), it remains unchanged");
3920 help1("The value of document charset should be in the range 0..255.");
3925 pux_xspace_code,pux_wcharother_code,pux_CJKinput_code,pux_charset_code:word_define(p, cur_val);
3926 puxg_cface_depth_code: if cur_val<>eqtb[p].int then
3927 @<Set PUTeX global parameter |puxgCfaceDepth|@>;
3929 print_err("Unknow integer parameter!");
3936 @ @<Set PUTeX global parameter |puxgCfaceDepth|@>=
3938 if cur_val>1000 then begin
3939 print_err("Improper `depth' value (");
3940 print_int(cur_val); print("). It is ignored");
3944 word_define(p,cur_val);
3945 cface_fw_default_depth:=convfix(puxg_cface_depth);
3947 while n<cface_ptr do begin
3948 cface_fw_depth[n]:=cface_fw_default_depth;
3952 while n<cfont_ptr do begin
3953 cfont_depth[n]:=fw_times_sd(cface_fw_depth[cfont_face[n]], cfont_size[n]);
3960 @d pux_set_cface_csp=0
3961 @d pux_set_cface_cesp=1
3962 @d pux_set_cface_depth=2
3963 @<Put each of \TeX's primitives into the hash table@>=
3964 primitive("PUXcfacecspace",pux_set_cface_attrib,pux_set_cface_csp);
3965 primitive("PUXcfacecespace",pux_set_cface_attrib,pux_set_cface_cesp);
3966 primitive("PUXcfacedepth",pux_set_cface_attrib,pux_set_cface_depth);
3968 @ @<Cases of |print_cmd_chr|...@>=
3969 pux_set_cface_attrib: begin
3971 pux_set_cface_csp:print_esc("PUXcfacecspace");
3972 pux_set_cface_cesp:print_esc("PUXcfacecespace");
3973 pux_set_cface_depth:print_esc("PUXcfacedepth");
3978 pux_set_cface_attrib: begin p:=cur_chr;
3979 @<Get the next non-blank non-call token@>;
3980 if cur_cmd=pux_set_cface then
3983 cface_num:=null_cface;
3984 print_err("Missing a CJK font face identifier");
3987 scan_optional_equals;
3988 if p=pux_set_cface_csp or p=pux_set_cface_cesp then
3989 @<Scan spacing dimension of CJK font face@>
3993 if cface_num<>null_cface then begin
3994 if p=pux_set_cface_csp then
3995 @<Modify the cspace factor of the specified chinese face@>
3996 else if p=pux_set_cface_cesp then
3997 @<Modify the cespace factor of the specified chinese face@>
3998 else if p=pux_set_cface_depth then
3999 @<Modify the depth factor of the specified chinese face@>;
4003 @ @<Other variables used by the procedure |prefixed_command|@>=
4004 @!width_value:integer; {width of space}
4005 @!stretch_value:integer; {stretch of space}
4006 @!shrink_value:integer; {shrink of space}
4009 @d puxg_set_cspace=0
4010 @d puxg_set_cespace=1
4012 @<Scan spacing dimension of CJK font face@>=
4014 scan_optional_equals;
4016 width_value:=cur_val;
4017 if scan_keyword("plus") then begin
4018 scan_int; stretch_value:=cur_val;
4020 else {make stretch value compatible to \PUTeX 3}
4021 if width_value < 250 and p = puxg_set_cspace then stretch_value:=125
4022 else stretch_value:=width_value/2;
4024 if scan_keyword("minus") then begin
4025 scan_int; shrink_value:=cur_val;
4027 else {make shrink value compatible to \PUTeX 3}
4028 if width_value > 0 then shrink_value:=width_value div 3
4029 else shrink_value:=-width_value div 3;
4032 @ @<Modify the cspace factor of the specified chinese face@>=
4034 if cface_csp_width[cface_num]<>width_value or
4035 cface_csp_stretch[cface_num]<>stretch_value or
4036 cface_csp_shrink[cface_num]<>shrink_value then begin
4037 cface_csp_width[cface_num]:=width_value;
4038 cface_csp_stretch[cface_num]:=stretch_value;
4039 cface_csp_shrink[cface_num]:=shrink_value;
4041 while n<cfont_ptr do begin
4042 if cface_num = cfont_face[n] then set_cglue_spec(n);
4048 @ @<Modify the cespace factor of the specified chinese face@>=
4050 if cface_cesp_width[cface_num]<>width_value or
4051 cface_cesp_stretch[cface_num]<>stretch_value or
4052 cface_cesp_shrink[cface_num]<>shrink_value then begin
4053 cface_cesp_width[cface_num]:=width_value;
4054 cface_cesp_stretch[cface_num]:=stretch_value;
4055 cface_cesp_shrink[cface_num]:=shrink_value;
4057 while n<cfont_ptr do begin
4058 if cface_num=cfont_face[n] then set_ceglue_spec(n);
4064 @ @<Modify the depth factor of the specified chinese face@>=
4066 cur_val:=convfix(cur_val);
4067 if cface_fw_depth[cface_num]<>cur_val then begin
4068 cface_fw_depth[cface_num]:=cur_val;
4070 while n<cfont_ptr do begin
4071 if cface_num=cfont_face[n] then
4072 cfont_depth[n]:=fw_times_sd(cface_fw_depth[cface_num], cfont_size[n]);
4079 @d pux_set_cfont_csp=0
4080 @d pux_set_cfont_cesp=1
4081 @<Put each of \TeX's primitives into the hash table@>=
4082 primitive("PUXcfontcspace",pux_set_cfont_attrib,pux_set_cfont_csp);
4083 primitive("PUXcfontcespace",pux_set_cfont_attrib,pux_set_cfont_cesp);
4085 @ @<Cases of |print_cmd_chr|...@>=
4086 pux_set_cfont_attrib: begin
4088 pux_set_cfont_csp:print_esc("PUXcfontcspace");
4089 pux_set_cfont_cesp:print_esc("PUXcfontcespace");
4094 pux_set_cfont_attrib: begin p:=cur_chr;
4095 @<Get the next non-blank non-call token@>;
4096 if cur_cmd = set_cfont then {the first form}
4100 else if cur_cmd = set_font and cur_chr=cur_font then
4101 cfont_num:=cur_cfont
4103 print_err("Missing CJK font identifier");
4104 help2("I was looking for a control sequence whose")@/
4105 ("current meaning is a CJK font command.");
4106 back_error; cfont_num:=null_cfont;
4108 scan_optional_equals;
4110 pux_set_cfont_csp: begin
4111 scan_glue(glue_val);
4112 width(cfont_glue_spec[cfont_num]):=width(cur_val);
4113 shrink(cfont_glue_spec[cfont_num]):=shrink(cur_val);
4114 stretch(cfont_glue_spec[cfont_num]):=stretch(cur_val);
4115 fast_delete_glue_ref(cur_val);
4117 pux_set_cfont_cesp: begin
4118 scan_glue(glue_val);
4119 width(cfont_ceglue_spec[cfont_num]):=width(cur_val);
4120 shrink(cfont_ceglue_spec[cfont_num]):=shrink(cur_val);
4121 stretch(cfont_ceglue_spec[cfont_num]):=stretch(cur_val);
4122 fast_delete_glue_ref(cur_val);
4127 @ @<Global variables@>=
4128 @!g_cspace_width:integer;
4129 @!g_cspace_shrink:integer;
4130 @!g_cspace_stretch:integer;
4131 @!g_cespace_width:integer;
4132 @!g_cespace_shrink:integer;
4133 @!g_cespace_stretch:integer;
4136 @d default_csp_width=50
4137 @d default_cesp_width=150
4139 g_cspace_width:=default_csp_width;
4140 g_cspace_shrink:=g_cspace_width div 3;
4141 g_cspace_stretch:=125;
4142 g_cespace_width:=default_cesp_width;
4143 g_cespace_shrink:=g_cespace_width div 3;
4144 g_cespace_stretch:=g_cespace_width div 2;
4146 @ @<Put each of \TeX's primitives into the hash table@>=
4147 primitive("puxgCspace",puxg_assign_space,puxg_set_cspace);
4148 primitive("puxgCEspace",puxg_assign_space,puxg_set_cespace);
4151 @ @<Cases of |print_cmd_chr|...@>=
4152 puxg_assign_space: begin
4153 if chr_code = puxg_set_cspace then
4154 print_esc("puxgCspace")
4155 else if chr_code = puxg_set_cespace then
4156 print_esc("puxgCEspace");
4162 puxg_assign_space: begin p:=cur_chr;
4163 @<Scan spacing dimension of CJK font face@>;
4164 if p = puxg_set_cspace then begin
4165 g_cspace_width:=width_value;
4166 g_cspace_stretch:=stretch_value;
4167 g_cspace_shrink:=shrink_value;
4169 while n < cface_ptr do begin
4170 cface_csp_width[n]:=width_value;
4171 cface_csp_shrink[n]:=shrink_value;
4172 cface_csp_stretch[n]:=stretch_value;
4176 while n<cfont_ptr do begin
4182 else if p = puxg_set_cespace then begin
4183 g_cespace_width:=width_value;
4184 g_cespace_stretch:=stretch_value;
4185 g_cespace_shrink:=shrink_value;
4188 while n < cface_ptr do begin
4189 cface_cesp_width[n]:=width_value;
4190 cface_cesp_shrink[n]:=shrink_value;
4191 cface_cesp_stretch[n]:=stretch_value;
4195 while n<cfont_ptr do begin
4202 @* \[61] Dump Font Info.
4204 @<Other variables used by the procedure |prefixed_command|@>=
4205 @!old_setting:0..max_selector; {holds |selector| setting}
4207 @ @<Put each of \TeX's primitives into the hash table@>=
4208 primitive("PUXdumpfontinfo",pux_dump_font_info,0);
4210 @ @<Cases of |print_cmd_chr|...@>=
4211 pux_dump_font_info: print_esc("PUXdumpfontinfo"); {TCW}
4214 pux_dump_font_info: begin old_setting:=selector; selector:=log_only;@/
4215 @<Print TeX fonts@>;@/
4216 @<Print CJK font faces@>;@/
4217 @<Print CJK fonts@>;@/
4218 @<Print font faces matching table@>;@/
4219 selector:=old_setting;
4222 @ @<Print TeX fonts@>=
4223 print_ln; print("Tex fonts"); print_ln;
4225 while n <= font_ptr do
4227 print_int(n); print(": "); print(font_name[n]);@/
4228 print(" dsize= "); print_scaled(font_dsize[n]); print("pt");@/
4229 print(" at "); print_scaled(font_size[n]); print("pt");@/
4230 print(" matched CJK font="); print_int(font_matching_table(n));
4234 @ @<Print CJK font faces@>=
4235 print("Chinese faces"); print_ln;
4237 while n < cface_ptr do
4239 print_int(n); print(": "); print("id="); print(cface[n]);@/
4240 print(" name="); print(cface_name[n]);@/
4241 print(" charset="); print_int(cface_charset[n]);@/
4242 print(" weight="); print_int(cface_weight[n]);@/
4243 print(" style="); print_int(cface_style[n]);@/
4244 print(" w="); print_fixword(cface_fw_width[n]);@/
4245 print(" h="); print_fixword(cface_fw_height[n]);@/
4246 print(" d="); print_fixword(cface_fw_depth[n]);@/
4250 @ @<Print CJK fonts@>=
4251 print("CJK fonts"); print_ln;
4253 while n < cfont_ptr do
4255 print_int(n); print(":face= ");
4256 print(cface[cfont_face[n]]);@/
4257 print(" dsize= "); print_scaled(cfont_dsize[n]); print("pt");@/
4258 print(" at "); print_scaled(cfont_size[n]); print("pt");@/
4262 @ @<Print font faces matching table@>=
4263 print("English/CJK font faces matching table"); print_ln;
4265 while n < ectbl_ptr do
4267 print_int(n); print(": "); print("eface="); print(ectbl_eface_name[n]);@/
4268 print(" cface_id="); print(cface[ectbl_cface_num(n)]);@/
4269 print(" cface_num="); print_int(ectbl_cface_num(n));@/
4273 @ @<Global variables@>=
4274 @!dvi_cf:internal_cfont_number; {the current chinese font}
4276 @ @<Output the CJK font definitions for all fonts that were used@>=
4277 while cfont_ptr>cfont_base do
4278 begin if cfont_used[cfont_ptr] then dvi_cfont_def(cfont_ptr);
4283 @ @<Change font |dvi_cf| to |f|@>=
4284 begin if not cfont_used[f] then
4285 begin dvi_cfont_def(f); cfont_used[f]:=true;
4287 dvi_out(cfnt); dvi_out((f-cfont_base-1) div 256); dvi_out((f-cfont_base-1) mod 256);
4291 @* \[62] Dump/undump \PUTeX\ internal information.
4293 @ @<Dump the CJK font face information@>=
4294 dump_int(cface_ptr);
4295 dump_int(cface_fw_default_depth);
4296 for k:=cface_base to cface_ptr-1 do begin
4298 dump_int(cface_name[k]);
4299 dump_int(cface_charset[k]);
4300 dump_int(cface_weight[k]);
4301 dump_int(cface_style[k]);
4302 dump_int(cface_fw_width[k]);
4303 dump_int(cface_fw_height[k]);
4304 dump_int(cface_fw_depth[k]);
4305 dump_int(cface_csp_width[k]);
4306 dump_int(cface_csp_shrink[k]);
4307 dump_int(cface_csp_stretch[k]);
4308 dump_int(cface_cesp_width[k]);
4309 dump_int(cface_cesp_shrink[k]);
4310 dump_int(cface_cesp_stretch[k]);
4312 print_int(k); print(": "); print("id="); print(cface[k]);@/
4313 print(" name="); print(cface_name[k]);@/
4314 print(" charset="); print_int(cface_charset[k]);@/
4315 print(" weight="); print_int(cface_weight[k]);@/
4316 print(" style="); print_int(cface_style[k]);@/
4317 print(" w="); print_fixword(cface_fw_width[k]);@/
4318 print(" h="); print_fixword(cface_fw_height[k]);@/
4319 print(" d="); print_fixword(cface_fw_depth[k]);@/
4322 print_int(cface_ptr-cface_base); print(" preloaded CJK font face");
4323 if cface_ptr<>cface_base+1 then print_char("s")
4325 @ @<Undump the CJK font face information@>=
4326 undump_size(cface_base)(max_cface)('cface max')(cface_ptr);
4327 undump_int(cface_fw_default_depth);
4328 for k:=cface_base to cface_ptr-1 do begin
4329 undump_size(0)(pool_size)('cface id')(cface[k]);
4330 undump_size(0)(pool_size)('cface name')(cface_name[k]);
4331 undump_size(0)(255)('charset size')(cface_charset[k]);
4332 undump_size(1)(1000)('cface weight')(cface_weight[k]);
4333 undump_size(0)(255)('cface style')(cface_style[k]);
4334 undump_int(cface_fw_width[k]);
4335 undump_int(cface_fw_height[k]);
4336 undump_int(cface_fw_depth[k]);
4337 undump_int(cface_csp_width[k]);
4338 undump_int(cface_csp_shrink[k]);
4339 undump_int(cface_csp_stretch[k]);
4340 undump_int(cface_cesp_width[k]);
4341 undump_int(cface_cesp_shrink[k]);
4342 undump_int(cface_cesp_stretch[k]);
4345 @ @<Dump the face matching table@>=
4346 dump_int(ectbl_ptr);
4347 for k:=min_ectbl to ectbl_ptr-1 do
4348 dump_int(ectbl_eface_name[k])
4350 @ @<Unump the face matching table@>=
4351 undump_size(min_ectbl)(max_ectbl)('ectbl_ptr')(ectbl_ptr);
4352 for k:=min_ectbl to ectbl_ptr-1 do
4353 undump_size(0)(pool_size)('ectbl eface name')(ectbl_eface_name[k])
4355 @ @<Dump the CJK font information@>=
4357 dump_int(cfont_ptr);
4358 for k:=default_cfont to cfont_ptr-1 do begin
4359 dump_int(cfont_face[k]);
4360 dump_int(cfont_dsize[k]);
4361 dump_int(cfont_size[k]);
4362 dump_int(cfont_width[k]);
4363 dump_int(cfont_height[k]);
4364 dump_int(cfont_depth[k]);
4365 dump_int(cfont_glue_spec[k]);
4366 dump_int(cfont_ceglue_spec[k]);
4368 print_int(k); print(":face= ");
4369 print(cface[cfont_face[k]]);@/
4370 print(" dsize= "); print_scaled(cfont_dsize[k]); print("pt");@/
4371 print(" at "); print_scaled(cfont_size[k]); print("pt");@/
4375 @ @<Undump the CJK font information@>=
4377 undump_size(cfont_base)(cfont_max)('cfont max')(cfont_ptr);
4378 for k:=default_cfont to cfont_ptr-1 do begin
4379 undump_size(cface_base)(max_cface)('cface max')(cfont_face[k]);
4380 undump_int(cfont_dsize[k]);
4381 undump_int(cfont_size[k]);
4382 undump_int(cfont_width[k]);
4383 undump_int(cfont_height[k]);
4384 undump_int(cfont_depth[k]);
4385 undump_int(cfont_glue_spec[k]);
4386 undump_int(cfont_ceglue_spec[k]);