ea4cd957787206ed5ab13e7bcb91c802bdb752ce
[oweals/cde.git] / cde / programs / dthelp / parser.ccdf / htag / helptag / help.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: help.c /main/4 1998/04/06 13:17:27 mgreess $ */
24 /*   Copyright (c) 1986, 1987, 1988, 1989 Hewlett-Packard Co. */
25 /* Miscellaneous Procedures for HP Tag/TeX translator */
26
27 #include "userinc.h"
28 #include "globdec.h"
29
30 /* Start an appendix */
31 void appstart(id, letter)
32 M_WCHAR *id, *letter;
33 {
34 M_WCHAR *p, *q, wnull;
35 char    *pc;
36 int      length;
37 long     xchapter;
38
39 rsectseq = FALSE;
40 if (inchapter)
41     {
42     chapter = 0;
43     inchapter = FALSE;
44     }
45 chapst = FALSE;
46 chapinc = 0;
47
48 /* Calculate the letter of the appendix in sequence */
49 if (! letter)
50     {
51     chapter++;
52     itoletter(chapter, 'A', chapstring, sizeof(chapstring) - 1);
53     }
54
55 /* User-specified letter */
56 else
57     {
58     for (p = letter, xchapter = 0; *p >= 'A' && *p <= 'Z' ; p++)
59         xchapter = 26 * xchapter + *p + 1 - 'A';
60     /* Test for overflow.  May occur if user omitted "id=" before
61      id and system interpreted what is really an id as the appendix
62      letter */
63     for (; *p >= '0' && *p <= '9' ; p++)
64         chapinc = 10 * chapinc + *p - '0';
65     if ((long) (int) xchapter != xchapter)
66         {
67         m_err1("%s: Too many characters in appendix letter", letter);
68         chapter++;
69         }
70     else chapter = (int) xchapter;
71     mbtowc(&wnull, "", 1);
72     for (pc = chapstring, q = letter; *q != wnull ; pc += length, q++)
73         {
74         char mbyte[32]; /* larger than the largest possible multibyte char */
75         length = wctomb(mbyte, *q);
76         if ((pc + length) >= (&chapstring[sizeof(chapstring) - 1]))
77             {
78             m_err1("%s: Too many characters in appendix letter", letter);
79             break;
80             }
81         strcpy(pc, mbyte);
82         }
83     *p = M_EOS;
84     }
85
86 fprintf(stderr, "\nAppendix %s. ", chapstring);
87
88 open_new_helpfile();
89
90 savid = checkid(id);
91 iderr = FALSE;
92
93 figno = 0;
94 tableno = 0;
95 footnoteno = 1;
96 }
97
98 void assert_hometopic_exists(M_NOPAR)
99 {
100 char *string =
101     GetDefaultHeaderString("UntitledElementDefaultHeadingString",
102                            M_SDATA,
103                            "Untitled");
104 if (nohometopic)
105     {
106     char    *pc;
107
108     mb_starthelpnode("_HOMETOPIC", FALSE);
109     nohometopic = FALSE;
110     pc = NULL;
111     if (savedtitle)
112         pc = MakeMByteString(savedtitle);
113     fprintf(outfile,
114             "%s%s%s",
115             "<TITLE><TYPE serif><WEIGHT bold><SIZE 14>",
116             pc  ? pc : string,
117             "</SIZE></WEIGHT></TYPE></TITLE>\n");
118     if (pc)
119         m_free(pc, "multi-byte string");
120     }
121 m_free(string, "GetDefaultHeaderString return");
122 }
123
124 /* Determine base name for files (i.e., input name without extension).
125    Open output and error files */
126 void basename(M_NOPAR)
127   {
128     char *p, *q;
129     int n;
130     char save;
131
132     m_errfile = NULL;
133     if (m_argc < 2) {
134       m_error("Specify input file");
135       exit(TRUE);
136       }
137     if (m_argc > 2 &&
138         (strchr(m_argv[2], 'f') || strchr(m_argv[2], 'F'))
139        ) filelist = TRUE;
140
141     /* Get installation directory */
142 #if defined(MSDOS)
143     for (p = m_argv[0]; *p ; p++);
144     for (; ; p--)
145       if (*p == dirsep || *p == ':') break;
146     p++;
147     save = *p;
148     *p = M_EOS;
149     install = m_malloc(strlen(m_argv[0]) + 1, "installation directory");
150     strcpy(install, m_argv[0]);
151     *p = save;
152
153 #else
154 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
155 #define CONTRIB "/usr/hphelp/bin/"
156
157     /* get our path if we can */
158     /* A hacked up ``which'', just to find our directory */
159     /* fills ``install'' with path to ourself */
160     {
161       char *path, *cp;
162       char buf[200];
163       char patbuf[BUFSIZ];
164       int quit, none;
165
166       quit = 0;
167       none = 1;
168
169       if ( *(m_argv[0]) == '/' ) {
170             /* fully qualified path to ourself was specified */
171             if (access(m_argv[0],1) == 0) {
172         /* if full path name exists and is executable */
173         /* get the dirname */
174         for (p = m_argv[0]; *p ; p++) ; /* end of string, (the hard way) */
175           /* backup to dirsep */
176           for (; ; p--) {
177             if (p < m_argv[0]) m_error("Internal Error.");
178             if (*p == dirsep) break; 
179             }
180           p++; /* just past the dirsep */
181           save = *p;
182           *p = M_EOS;
183           install = (char *)m_malloc(strlen(m_argv[0]) + 1, "installation directory");
184           strcpy(install, m_argv[0]);
185           *p = save;
186
187           none = 0; /* we've got it. */
188           }
189         else {
190           m_error("Internal Error (which).");
191           }
192         }
193       else {
194         /* not fully specified, check each component of path for ourself */
195         strcpy(patbuf, getenv("PATH"));
196         path = patbuf;
197         cp = path;
198
199         while(1) {
200           cp = strchr(path, ':');
201           if (cp == NULL)
202             quit++;
203                 else
204             *cp = '\0';
205           sprintf(buf, "%s/%s", path, m_argv[0]);
206
207           if (access(buf, 1) == 0) {
208             install = (char*) m_malloc(strlen(path) + 1,
209                       "installation directory");
210             strcpy(install, path);
211             none = 0;
212             }
213           /* else, not an error if we can't find a particular one. */
214
215           path = ++cp;
216           if (quit || !none) {
217             break; /* either out of paths, or we found it. */
218             }
219           }  /* end while */
220      }
221      
222      if (none) {
223           /* can't get it, use default */
224           install = (char*) m_malloc(strlen(CONTRIB) + 1,
225                                      "installation directory");
226           strcpy(install, CONTRIB);
227      }
228      /* else -- we've got it */
229 }
230
231 #else
232  Get installation directory
233 #endif
234 #endif
235
236     /* Set default working directory (from input filename) */
237     for (p = strchr(m_argv[1], M_EOS); p > m_argv[1] ; p--)
238       if (*(p - 1) == dirsep
239 #if defined(MSDOS)
240           || *(p - 1) == ':'
241 #endif
242           ) break;
243     if (p > m_argv[1]) {
244       save = *p;
245       *p = M_EOS;
246       work = (char *) m_malloc(strlen(m_argv[1]) + 1, "working directory");
247       strcpy(work, m_argv[1]);
248       indir = (char *) m_malloc(strlen(m_argv[1]) + 1, "input directory");
249       strcpy(indir, m_argv[1]);
250       *p = save;
251       }
252     else {
253       indir = NULL;
254       }
255
256     /* Build base name */
257     q = strchr(m_argv[1], M_EOS);
258     while (q > m_argv[1] && *q != '.' && *q != dirsep) q--;
259     defaultext = (LOGICAL) (*q != '.');
260     if (! defaultext) *q = M_EOS;
261     nodirbase = (char *)
262                 m_malloc(strlen(p) + 1, "basename without directory");
263     strcpy(nodirbase, p);
264     /* Get working directory option, if specified */
265     n = strlen(p);
266     base = (char *) m_malloc(n + strlen(".htg") + 1, "basename");
267     strcpy(base, p);
268     base[n] = '.';
269     baseext = base + n + 1;
270     if (! defaultext)
271       if (*(q + 1))
272         *q = '.';
273
274     options(TRUE); /* pluck only length changing optins */
275     if (usingshortnames) {
276      /* Build short versions of basename */
277      /* set up global helpbase and helpext */
278      helpbase = (char *) m_malloc(strlen(work) + BASENAME_LIMIT + PRE_EXTENSION_LIMIT + strlen(".ext") + 1, "help basename");
279      strcpy(helpbase, work);
280      strncat(helpbase, nodirbase, BASENAME_LIMIT);
281      helpext = helpbase + strlen(helpbase);
282 }
283 else { /* Build long names */
284      /* set up global helpbase and helpext */
285      helpbase = (char *) m_malloc(strlen(work) + strlen(nodirbase) + PRE_EXTENSION_LIMIT + strlen(".ext") + 1, "help basename");
286      strcpy(helpbase, work);
287      strcat(helpbase, nodirbase);
288      helpext = helpbase + strlen(helpbase);
289 }
290     /* Open error files */
291     if (filelist) {
292       m_openchk(&m_errfile, "filelist.err", "w");
293       }
294     else {
295       strcpy(helpext, ".err");
296       m_openchk(&m_errfile, helpbase, "w");
297       }
298     }
299
300
301 /* This procedure starts a CHAPTER OR PART, depending on the character
302    array "type," which should only contain "part" or "chapter."  Note
303    that PART is supported only for calculator.  */
304 void chapstart(id, number, type)
305 M_WCHAR *id, *number;
306 char type[];          /* values: locase "chapter" or "part" ONLY  */
307 {
308 M_WCHAR *p, *q, *wc;
309 int i;
310 char *mbyte, *pc;
311 int   length;
312
313 char *chapterPrefixString =
314   GetDefaultHeaderString("ChapterElementDefaultHeadingString",
315                          M_SDATA,
316                          "Chapter");
317 char *chapterSuffixString =
318   GetDefaultHeaderString("ChapterSuffixElementDefaultHeadingString",
319                          M_SDATA,
320                          "");
321 char *partPrefixString =
322   GetDefaultHeaderString("PartElementDefaultHeadingString",
323                          M_SDATA,
324                          "Part");
325 char *partSuffixString =
326   GetDefaultHeaderString("PartSuffixElementDefaultHeadingString",
327                          M_SDATA,
328                          "");
329
330 rsectseq = FALSE;   /* CHAPTERs only; irrelevant for PART */
331 chapst = FALSE;     /* CHAPTERs only; irrelevant for PART */
332 chapinc = 0;
333 if (! number)
334     {
335     if ( *type == 'c' )
336         {
337         chapter++;      /* CHAPTER processing */
338         m_itoa(chapter, chapstring);
339         }
340     else
341         {
342         part++;
343         m_itoa(part, chapstring);
344         }
345     }
346 else
347     {
348     mbyte = MakeMByteString(number);
349     chapter = atoi(mbyte);
350     m_free(mbyte,"multi-byte string");
351
352     for (p = number; *p >= '0' && *p <= '9' ; p++);
353     for (; *p >= 'A' && *p <= 'Z' ; p++)
354         chapinc = 26 * chapinc + *p + 1 - 'A';
355
356     mbyte = MakeMByteString(number);
357     if (strlen(mbyte) + 1 > sizeof(chapstring))
358         {
359         wc = MakeWideCharString(type);
360         m_err2("%s: Too many characters in %s number", number, wc);
361         m_free(wc,"wide character string");
362         strncpy(chapstring, mbyte, sizeof(chapstring) - 1);
363         }
364     else
365         strcpy(chapstring, mbyte);
366     m_free(mbyte,"multi-byte string");
367
368     pc = chapstring;
369     while (*pc)
370         {
371         if ((length = mblen(pc,32)) == 1)
372             *pc = isupper(*pc) ? tolower(*pc) : *pc;
373         pc += length;
374         }
375     }
376 if (*type == 'c')
377     { /* chapter, not part */
378          open_new_helpfile();
379     }
380 savid = checkid(id);
381 iderr = FALSE;
382
383 figno = 0;
384 tableno = 0;
385 footnoteno = 1;
386 fprintf(stderr,
387         "\n%s %s%s. ",
388         *type=='c' ? chapterPrefixString : partPrefixString,
389         chapstring,
390         *type=='c' ? chapterSuffixString : partSuffixString
391         );
392 m_free(chapterPrefixString, "GetDefaultHeaderString return");
393 m_free(partPrefixString, "GetDefaultHeaderString return");
394 if (*chapterSuffixString)
395     m_free(chapterSuffixString, "GetDefaultHeaderString return");
396 if (*partSuffixString)
397     m_free(partSuffixString, "GetDefaultHeaderString return");
398 }
399
400 /*****************************************************************
401 *****************************************************************
402  CDROM routines:  check to see if sdata is supported in cdrom
403 */ 
404 #define STATIC static
405 /*
406  * define arrays specifing laserrom defined entities.
407  * these are used to override "texchar.ent" SDATA && PI definitions.
408  */
409 STATIC struct
410 {
411     char *entityName;
412     char *entityData;
413 } DefPIEntity[] =
414 {
415     {"D-", ""},
416     {"m-d-", ""},
417     /*
418      * the last entry in this array should always be
419      * '{NULL, NULL}'
420      */
421     {NULL, NULL}
422 };
423
424 STATIC struct
425 {
426     char *entityName;
427     char *entityData;
428 } DefSDataEntity[] =
429 {
430     {"EMPTY", ""},
431     {"MINUS", "\\symbol{4}"},
432     {"PM", "+-"},
433     {"DIV", "\\symbol{5}"},
434     {"TIMES", "\\times "},
435     {"LEQ", "\\symbol{12}"},
436     {"GEQ", "\\symbol{13}"},
437     {"NEQ", "\\symbol{14}"},
438     {"COPY", "(c)"},
439     {"REG", "(R)"},
440     {"TM", "\\special{{PLU}}TM\\special{{PLD}}"},
441     {"ELLIPSIS", "\\symbol{18}"},
442     {"VELLIPSIS", "\\symbol{7}"},
443     {"DEG", "degree"},
444     {"SQUOTE", "\\symbol{8}"},
445     {"DQUOTE", "\\symbol{9}"},
446     {"ENDASH", "\\symbol{10}"},
447     {"EMDASH", "\\symbol{21}"},
448     {"VBLANK", "_"},
449     {"CENTS", "cents"},
450     {"STERLING", "sterling"},
451     {"PELLIPSIS", "...."},
452     {"MSPECCHAR", ""},
453     {"SIGSPACE", "\\ "},
454     {"HALFSPACE", "\\ "},
455     {"MICRO", "\\symbol{24}"},
456     {"OHM", "ohm"},
457     {"UP", "up arrow"},
458     {"DOWN", "down arrow"},
459     {"LEFT", "left arrow"},
460     {"RIGHT", "right arrow"},
461     {"HOME", "home arrow"},
462     {"BACK", "[[backspace]]"},
463     {"DATE", "\\date "},
464     {"TIME", "\\time "},
465     {"A.M.", "am"},
466     {"P.M.", "pm"},
467     {"MINUTES", "\\squote "},
468     {"SECONDS", "\\dquote "},
469     {"M-SPECCHAR", ""},
470     {"alpha", "alpha"},
471     {"beta", "beta"},
472     {"gamma", "gamma"},
473     {"delta", "delta"},
474     {"epsilon", "epsilon"},
475     {"varepsilon", "varepsilon"},
476     {"zeta", "zeta"},
477     {"eta", "eta"},
478     {"theta", "theta"},
479     {"vartheta", "vartheta"},
480     {"iota", "iota"},
481     {"kappa", "kappa"},
482     {"lambda", "lambda"},
483     {"mu", "mu"},
484     {"nu", "nu"},
485     {"xi", "xi"},
486     {"pi", "pi"},
487     {"varpi", "varpi"},
488     {"rho", "rho"},
489     {"varrho", "varrho"},
490     {"sigma", "sigma"},
491     {"varsigma", "varsigma"},
492     {"tau", "tau"},
493     {"upsilon", "upsilon"},
494     {"phi", "phi"},
495     {"varphi", "varphi"},
496     {"chi", "chi"},
497     {"psi", "psi"},
498     {"omega", "omega"},
499     {"UGamma", "Gamma"},
500     {"UDelta", "Delta"},
501     {"UTheta", "Theta"},
502     {"ULambda", "Lambda"},
503     {"UXi", "Xi"},
504     {"UPi", "Pi"},
505     {"USigma", "Sigma"},
506     {"UUpsilon", "Upsilon"},
507     {"UPhi", "Phi"},
508     {"UPsi", "Psi"},
509     {"UOmega", "Omega"},
510     {"CA", "\\it{A}"},
511     {"CD", "\\it{D}"},
512     {"CG", "\\it{G}"},
513     {"CJ", "\\it{J}"},
514     {"CM", "\\it{M}"},
515     {"CP", "\\it{P}"},
516     {"CS", "\\it{S}"},
517     {"CV", "\\it{V}"},
518     {"CY", "\\it{Y}"},
519     {"CB", "\\it{B}"},
520     {"CE", "\\it{E}"},
521     {"CH", "\\it{H}"},
522     {"CK", "\\it{K}"},
523     {"CN", "\\it{N}"},
524     {"CQ", "\\it{Q}"},
525     {"CT", "\\it{T}"},
526     {"CW", "\\it{W}"},
527     {"CZ", "\\it{Z}"},
528     {"CC", "\\it{C}"},
529     {"CF", "\\it{F}"},
530     {"CI", "\\it{I}"},
531     {"CL", "\\it{L}"},
532     {"CO", "\\it{O}"},
533     {"CR", "\\it{R}"},
534     {"CU", "\\it{U}"},
535     {"CX", "\\it{X}"},
536     {"aleph", "aleph"},
537     {"hbar", "hbar"},
538     {"imath", "\\it{i}"},
539     {"jmath", "\\it{j}"},
540     {"ell", "\\it{l}"},
541     {"wp", "wp"},
542     {"Re", "Re"},
543     {"Im", "Im"},
544     {"partial", "d"},
545     {"infty", "infinity"},
546     {"S", "section"},
547     {"szero", "szero"},
548     {"prime", "\\symbol{8}"},
549     {"emptyset", "empty set"},
550     {"nabla", "nabla"},
551     {"surd", "x"},
552     {"top", "top"},
553     {"bot", "bottom"},
554     {"vbar", "||"},
555     {"angle", "angle"},
556     {"triangle", "triangle"},
557     {"backslash", "\\\\"},
558     {"P", "paragraph"},
559     {"forall", "forall"},
560     {"exists", "exists"},
561     {"neg", "^"},
562     {"flat", "\\it{b}"},
563     {"natural", "natural"},
564     {"sharp", "\\#"},
565     {"clubsuit", "clubs"},
566     {"diamondsuit", "diamonds"},
567     {"heartsuit", "hearts"},
568     {"spadesuit", "spades"},
569     {"sum", "sum"},
570     {"prod", "prod"},
571     {"coprod", "coprod"},
572     {"int", "integral"},
573     {"oint", "ointegral"},
574     {"bigcap", "bigcap"},
575     {"bigcup", "bigcup"},
576     {"bigsqcup", "bigsqcup"},
577     {"bigvee", "bigvee"},
578     {"bigwedge", "bigwedge"},
579     {"bigodot", "bigodot"},
580     {"bigotimes", "bigotimes"},
581     {"bigoplus", "bigoplus"},
582     {"biguplus", "biguplus"},
583     {"mp", "-+"},
584     {"setminus", "\\\\"},
585     {"cdot", "\\special{{PLU}}.\\special{{PLD}}"},
586     {"ast", "*"},
587     {"star", "*"},
588     {"diamond", "diamond"},
589     {"circ", "circ"},
590     {"bullet", "bullet"},
591     {"cap", "cap"},
592     {"cup", "cup"},
593     {"uplus", "uplus"},
594     {"sqcap", "sqcap"},
595     {"sqcup", "sqcup"},
596     {"triangleleft", "triangleleft"},
597     {"triangleright", "triangleright"},
598     {"wr", "wr"},
599     {"bigcirc", "bigcirc"},
600     {"bigtriangleup", "triangleup"},
601     {"bigtriangledown", "triangledown"},
602     {"vee", "v"},
603     {"wedge", "wedge"},
604     {"oplus", "oplus"},
605     {"ominus", "ominus"},
606     {"otimes", "otimes"},
607     {"oslash", "oslash"},
608     {"odot", "odot"},
609     {"dagger", "*"},
610     {"ddagger", "**"},
611     {"amalg", "amalg"},
612     {"prec", "prec"},
613     {"preceq", "preceq"},
614     {"ll", "<<"},
615     {"subset", "subset"},
616     {"subseteq", "subseteq"},
617     {"sqsubseteq", "sqsubseteq"},
618     {"in", "in"},
619     {"vdash", "|-"},
620     {"smile", "smile"},
621     {"frown", "frown"},
622     {"succ", "succ"},
623     {"succeq", "succeq"},
624     {"gg", ">>"},
625     {"supset", "supset"},
626     {"supseteq", "supseteq"},
627     {"sqsupseteq", "sqsupseteq"},
628     {"ni", "notin"},
629     {"dashv", "-|"},
630     {"mid", "|"},
631     {"parallel", "||"},
632     {"equiv", "equiv"},
633     {"sim", "sim"},
634     {"simeq", "simeq"},
635     {"asymp", "asymp"},
636     {"approx", "approx"},
637     {"cong", "cong"},
638     {"bowtie", "bowtie"},
639     {"propto", "propto"},
640     {"models", "|="},
641     {"doteq", "doteq"},
642     {"perp", "perp"},
643     {"not-l", "not <"},
644     {"not-leq", "not <="},
645     {"not-prec", "not prec"},
646     {"not-preceq", "not preceq"},
647     {"not-subset", "not subset"},
648     {"not-subseteq", "not subset equal"},
649     {"not-sqsubseteq", "not sqsubseteq"},
650     {"not-eq", "not ="},
651     {"not-sim", "not sim"},
652     {"not-approx", "not approx"},
653     {"not-asymp", "not asymp"},
654     {"not-g", "not >"},
655     {"not-geq", "not >="},
656     {"not-succ", "not succ"},
657     {"not-succeq", "not succeq"},
658     {"not-supset", "not supset"},
659     {"not-supseteq", "not supseteq"},
660     {"not-sqsupseteq", "not sqsupseteq"},
661     {"not-equiv", "not equiv"},
662     {"not-simeq", "not simeq"},
663     {"not-cong", "not cong"},
664     {"leftarrow", "<-"},
665     {"bigleftarrow", "<="},
666     {"rightarrow", "->"},
667     {"bigrightarrow", "=>"},
668     {"leftrightarrow", "<->"},
669     {"bigleftrightarrow", "<=>"},
670     {"mapsto", "|->"},
671     {"hookleftarrow", "hookleftarrow"},
672     {"leftharpoonup", "leftharpoonup"},
673     {"leftharpoondown", "leftharpoondown"},
674     {"rightleftharpoons", "rightleftharpoons"},
675     {"uparrow", "uparrow"},
676     {"biguparrow", "biguparrow"},
677     {"downarrow", "downarrow"},
678     {"bigdownarrow", "bigdownarrow"},
679     {"updownarrow", "updownarrow"},
680     {"bigupdownarrow", "bigupdownarrow"},
681     {"longleftarrow", "<--"},
682     {"biglongleftarrow", "<=="},
683     {"longrightarrow", "-->"},
684     {"biglongrightarrow", "==>"},
685     {"longleftrightarrow", "<-->"},
686     {"biglongleftrightarrow", "<==>"},
687     {"longmapsto", "|-->"},
688     {"hookrightarrow", "hookrightarrow"},
689     {"rightharpoonup", "rightharpoonup"},
690     {"rightharpoondown", "rightharpoondown"},
691     {"nearrow", "NEarrow"},
692     {"searrow", "SEarrow"},
693     {"swarrow", "SWarrow"},
694     {"nwarrow", "NWarrow"},
695     {"half", "1/2"},
696     {"third", "1/3"},
697     {"quarter", "1/4"},
698     {"threequarter", "3/4"},
699     {"fifth", "1/5"},
700     {"sixth", "1/6"},
701     {"eighth", "1/8"},
702     {"sixteenth", "1/16"},
703     {"space", "\\symbol{20}"},
704     {"INSTMAN", "instman"},
705     {"HAZVOLT", "hazvolt"},
706     {"GROUND", "ground"},
707     {"DCVOLT", "dcvolt"},
708     {"NEGPULSE", "negpulse"},
709     {"POSPULSE", "pospulse"},
710     {"SINEWAVE", "sinewave"},
711     {"SAWWAVE", "sawwave"},
712     {"RAMPWAVE", "rampwave"},
713     {"TRIWAVE", "triwave"},
714     {"SQWAVE", "sqwave"},
715     /*
716      * the last entry in this array should always be
717      * '{NULL, NULL}'
718      */
719     {NULL, NULL}
720 };
721
722
723 /* Verify Tag dimension, else issue error message */
724 M_WCHAR *checkdimen( val, paramname, elt )
725 M_WCHAR *val;
726 M_WCHAR *paramname;
727 M_WCHAR *elt;
728 {
729 /* returns val if a valid TeX dimension, else NULL */
730 M_WCHAR *valid = NULL;
731
732 if ( val == NULL ) return ( NULL );
733 if ((valid = okdimen(val)) != NULL) return(valid);
734 if ( valid == NULL )
735     {
736     M_WCHAR *wc_stago, *wc_tagc;
737
738     wc_stago = MakeWideCharString(m_stago);
739     wc_tagc  = MakeWideCharString(m_tagc);
740     m_err5 ("[%s] Illegal value of %s for %s%s%s",
741            val,
742            paramname,
743            wc_stago,
744            elt,
745            wc_tagc );
746     m_free(wc_stago,"wide character string");
747     m_free(wc_tagc,"wide character string");
748     }
749 return ( valid );
750 }
751
752
753 M_WCHAR *mb_checkdimen( val, paramname, elt )
754 M_WCHAR *val;
755 char *paramname;
756 char *elt;
757 {
758 M_WCHAR *wc_paramname, *wc_elt, *retval;
759
760 wc_paramname = MakeWideCharString(paramname);
761 wc_elt       = MakeWideCharString(elt);
762
763 retval = checkdimen(val, wc_paramname, wc_elt);
764
765 m_free(wc_paramname,"wide character string");
766 m_free(wc_elt,"wide character string");
767 }
768
769 /* Check through search (like openent()) paths of SYSTEM entity name to
770    construct fully qualified or relative path names, if any */
771 M_WCHAR *checkent(entcontent)
772 M_WCHAR *entcontent;
773 {
774 M_WCHAR *filename;
775 SEARCH  *searchp;
776 char    *mb_entc, mb_filen[2048];
777 int      dir_leng, econt_leng;
778
779 mb_entc = MakeMByteString(entcontent);
780 if (access(mb_entc, 04)==0)
781     {  /* entcontent is readable */
782     filename = (M_WCHAR *) m_malloc(w_strlen(entcontent) + 1,
783                                     "checkent figinpath");
784     w_strcpy(filename, entcontent);
785     m_free(mb_entc,"multi-byte string");
786     return(filename);
787     }
788
789 econt_leng = strlen(mb_entc);
790 for (searchp = path; searchp ; searchp = searchp->next)
791     {
792     if (((dir_leng = strlen(searchp->directory)) + econt_leng) >= 2048)
793         {
794         M_WCHAR *wc;
795
796         wc = MakeWideCharString(searchp->directory);
797         m_err2("%s and %s overflow the file name space",
798                wc,
799                entcontent);
800         m_free(wc,"wide character string");
801         continue;
802         }
803     strcpy(mb_filen, searchp->directory);
804     strcpy(mb_filen + dir_leng, mb_entc);
805     if (access(mb_filen, 04)==0)  /* entcontent is readable */
806         {
807         m_free(mb_entc,"multi-byte string");
808         return MakeWideCharString(mb_filen);
809         }
810     }
811
812 m_free(mb_entc,"multi-byte string");
813 return(NULL);
814 }
815
816
817 /* Called at end of manual to report terms that occurred in the document
818    but not entered in the glossary */
819 void checkgloss(M_NOPAR)
820 {
821 int n;
822 M_WCHAR id[MAXTERM + 1];
823 M_TRIE *node[MAXTERM + 1];
824 M_TRIE *current;
825
826 if (! gtree.data) return;
827 n = 0;
828 current = gtree.data;
829 while (TRUE)
830     {
831     id[n] = current->symbol;
832     node[n] = current->next;
833     if (! id[n])
834         {
835         if ((unsigned) current->data != DEFINETERM)
836             m_err1("No glossary definition for %s", id);
837         current = current->next;
838         while (! current)
839             {
840             n--;
841             if (n < 0) return;
842             current = node[n];
843             }
844         }
845     else
846         {
847         current = current->data;
848         n++;
849         }
850     }
851 }
852
853                 
854 /* End Error _DtMessage macro \starterrmsg call, check to see if Error _DtMessage
855    head is user specified or default */
856 void checkmsghead(M_NOPAR)
857 {
858 char *string =
859     GetDefaultHeaderString("MessagesElementDefaultHeadingString",
860                            M_SDATA,
861                            "Messages");
862 if (emsghead == DEFHEAD)
863     {  /* head not output yet */
864     fprintf(outfile,
865             "%s%s%s",
866             "<TITLE><TYPE serif><WEIGHT bold><SIZE 14>",
867             string,
868             "</TYPE></WEIGHT></SIZE></TITLE>\n");
869     emsghead = FALSE;
870     }
871 else if (emsghead == USERHEAD)
872     {  /* user specified head */
873     emsghead = FALSE;
874     }
875 m_free(string, "GetDefaultHeaderString return");
876 }  /* end checkmsghead() */
877
878                 
879 /* Verify that val is an acceptable real number value */
880 #if defined(M_PROTO)
881 M_WCHAR *
882 checkreal (M_WCHAR *val, M_WCHAR *paramname, LOGICAL msgout, M_WCHAR *elt)
883 #else
884 M_WCHAR *checkreal (val, paramname, msgout, elt)
885 M_WCHAR *val, *paramname;
886 LOGICAL msgout;
887 M_WCHAR *elt;
888 #endif
889 {
890 /* returns val if a valid real number, else NULL */
891 double num;
892 M_WCHAR *valid = NULL;
893 char     s1[M_NAMELEN+1];
894 char    *mbyte;
895
896 if (val == NULL) return NULL;
897
898 mbyte = MakeMByteString(val);
899
900 if (sscanf (mbyte, "%lf", &num ) == 1 ) valid = val;
901
902 if (sscanf(mbyte, "%lf%s", &num, s1 ) == 2 )
903     valid = NULL; /* no characters allowed  */
904
905 if ( valid == NULL )
906     {
907     M_WCHAR *wc_stago, *wc_tagc;
908
909     if (msgout)
910         {
911         wc_stago = MakeWideCharString(m_stago);
912         wc_tagc  = MakeWideCharString(m_tagc);
913         m_err5("[%s] Illegal value of %s for %s%s%s",
914                val,
915                paramname,
916                wc_stago,
917                elt,
918                wc_tagc );
919         m_free(wc_stago,"wide character string");
920         m_free(wc_tagc,"wide character string");
921         }
922     }
923
924 m_free(mbyte,"multi-byte string");
925 return ( valid );
926 } /* END checkreal procedure */
927
928
929 /* end a help node */
930 void endhelpnode(M_NOPAR)
931 {
932 }
933
934 /* End code for <EX> and <VEX> */
935 void exvexend (textsize)
936 M_WCHAR *textsize;
937 {
938 int tsize;
939
940 tsize = vextextsize(textsize);
941 if (tsize==NORMAL)
942     {
943     fputs("</SPACING></TYPE></PARAGRAPH>\n\n", outfile);
944     }      
945 else
946     {  /* textsize is either SMALLER or SMALLEST */
947     fputs("</SIZE>\n</SPACING></TYPE></PARAGRAPH>\n\n", outfile);
948     }
949 }  /* END exvexend() */
950
951
952 /* Starting stuff for <EX> and <VEX> */
953 #if defined(M_PROTO)
954 void exvexstart (M_WCHAR *type, M_WCHAR *textsize, char *listinfo)
955 #else
956 void exvexstart (type, textsize, listinfo)
957 M_WCHAR *type, *textsize;
958 char *listinfo;
959 #endif
960 {
961 int tsize;
962
963 STARTSTUFF
964 rshnewclear();
965 parspace();
966 tsize = vextextsize(textsize);
967 if (tsize==NORMAL)
968     {
969     fprintf(outfile,
970     "<PARAGRAPH%s firstindent %d leftindent %d nowrap><TYPE serif><SPACING m>",
971             listinfo,
972             LEFTINDENT,
973             LEFTINDENT);
974     }      
975 else
976     {  /* textsize is either SMALLER or SMALLEST */
977     fprintf(outfile,
978      "<PARAGRAPH%s firstindent %d leftindent %d nowrap><TYPE serif><SPACING m>",
979             listinfo,
980             LEFTINDENT,
981             LEFTINDENT);
982     if (tsize==SMALLER)
983         {
984         fputs("<SIZE 8>", outfile);
985         }
986     else
987         {
988         fputs("<SIZE 6>", outfile);
989         }
990     }
991 }  /* END exvexstart() */
992
993
994 /* construct a qualified file name */
995 int mb_getqualified ( qualname, unqualname )
996 char *qualname;
997 char *unqualname;
998 {
999 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
1000 FILE *f;
1001 #endif
1002 char fn[FNAMELEN];
1003 char tokstr [ 20 ], *gp, *p, *pp, *fnp, curdir[FNAMELEN-1];
1004 int roomleft = FNAMELEN - 1;
1005
1006 if (!unqualname)
1007     {
1008     *qualname = M_EOS;
1009     return( 0 );
1010     }
1011
1012 if (strlen(unqualname) < FNAMELEN)
1013     strcpy(fn, unqualname );
1014 else
1015     {
1016     m_mberr1("Internal Error. File name too long for qualifying: %s",
1017              unqualname);
1018     return (-1);
1019     }
1020
1021 fnp = fn;
1022
1023 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
1024 qualname[0] = '\0';
1025 gp = qualname + strlen(qualname);
1026 roomleft = roomleft - strlen(qualname);
1027
1028 /* if path is from root, tack that on, else tack on the current
1029  directory (for the referenced drive, if MS-DOS) */
1030 /* We assume FNAMELEN is at least three (3), so no range checking here */
1031 if ( *fnp == CSEP )
1032     {
1033     strcat(qualname, SSEP);
1034     roomleft--;
1035     ++fnp;
1036     }
1037 else
1038     {
1039     f = popen("/bin/pwd", "r");
1040     fscanf(f, "%s", gp);
1041     pclose(f);
1042     if (strlen(gp) >= roomleft)
1043         {
1044         m_mberr1("Internal error: possible stray pointer in getqualified(): %s",
1045                  gp);
1046         return(-1);
1047         }
1048     strcat(qualname,SSEP);
1049     roomleft--;
1050     }
1051 #else
1052 /* if MS-DOS, force to upper case, then get drive spec */
1053 strupr ( fn );
1054 if ( fn[1] == ':' ) {
1055 strncpy ( qualname, fn, 2 );
1056 fnp += 2;
1057 }
1058 else {
1059 getcwd(qualname, roomleft);
1060 }
1061 qualname[2] = '\0';
1062 gp = qualname + strlen ( qualname );
1063 roomleft = roomleft - strlen ( qualname );
1064 /* if path is from root, tack that on, else tack on the current
1065  directory (for the referenced drive, if MS-DOS) */
1066 if ( *fnp == CSEP ) {
1067 strcat ( qualname, SSEP );
1068 roomleft--;
1069 ++fnp;
1070 }
1071 else {
1072 /* assume current directory always !!! */
1073 *gp = CSEP;
1074 getcwd(curdir, FNAMELEN-1);
1075 if (*curdir != *qualname) {
1076   m_err1("Relative directory %s for non-current drive, can't qualify",
1077           unqualname);
1078   return (-1);
1079   }
1080 if (strlen(curdir) > 3) {
1081   if ((strlen(curdir+3)+1) < roomleft) {  /* "1" for SSEP */
1082     strcpy( gp+1, curdir+3 );
1083     strcat ( qualname, SSEP );
1084     roomleft = roomleft - strlen(curdir+3) - 1;  /* "1" for SSEP */
1085     }
1086   else {
1087     m_err1("Internal error. File name too long for qualifying: %s",
1088       unqualname);
1089     return (-1);
1090     }
1091   }
1092 }
1093 #endif
1094
1095 strcpy(tokstr, " \r\n\t");
1096 strcat(tokstr, SSEP);
1097 p = NULL;
1098 do  {
1099     p = strtok(( p == NULL ) ? fnp : NULL, tokstr);
1100     if ( p == NULL ) break;
1101     if ( *p == '.' ) /* alias */
1102         {
1103         if ( *(p+1) == '.' ) /* parent */
1104             {
1105             *strrchr(qualname, CSEP) = '\0';
1106             pp = strrchr(qualname, CSEP);
1107             if (pp == NULL) /* FAIL */
1108                 {
1109                 m_mberr1("Internal error. Failed in qualifying %s", unqualname);
1110                 return ( -1 );
1111                 }
1112             else
1113                 {
1114                 *(pp+1) = '\0';
1115                 }
1116             }
1117         }
1118     else
1119         {
1120         if ((strlen(p)+1) < roomleft)
1121             {  /* "1" for SSEP */
1122             strcat(qualname, p);
1123             strcat(qualname, SSEP);
1124             roomleft = roomleft - strlen(p) - 1;
1125             }
1126         else
1127             {
1128             m_mberr1("Internal error. File name too long for qualifying: %s",
1129                      unqualname);
1130             return (-1);
1131             }
1132         }
1133     }
1134 while (1);
1135 *strrchr(qualname, CSEP) = '\0';
1136
1137 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
1138 #else
1139 strupr ( qualname );
1140 #endif
1141
1142 return ( 0 );
1143 }  /* end mb_getqualified */
1144
1145
1146 int getqualified (qualname, unqualname)
1147 M_WCHAR *qualname;
1148 M_WCHAR *unqualname;
1149 {
1150 int retval;
1151 char mb_qualname[FNAMELEN],
1152      mb_unqualname[FNAMELEN];
1153
1154 wcstombs(mb_qualname, qualname, FNAMELEN);
1155 wcstombs(mb_unqualname, unqualname, FNAMELEN);
1156
1157 retval = mb_getqualified(mb_qualname, mb_unqualname);
1158
1159 mbstowcs(qualname, mb_qualname, FNAMELEN);
1160 mbstowcs(unqualname, mb_unqualname, FNAMELEN);
1161
1162 return retval;
1163 }
1164
1165
1166 /* handle the common link and graphic code for <p> and <image> */
1167 void
1168 handle_link_and_graphic(parent,
1169                         gentity,
1170                         gposition,
1171                         ghyperlink,
1172                         glinktype,
1173                         gdescription)
1174 M_WCHAR *parent, *gentity, *gposition, *ghyperlink, *glinktype, *gdescription;
1175 {
1176 unsigned char etype, wheredef;
1177 char *mb_content;
1178 static M_WCHAR empty = M_EOS;
1179
1180 /* handle graphic specific code */
1181 /* initialize some stuff first:
1182 - file is the entity name,
1183 - f_file is the content of the entity, used only if f_content nonNULL
1184 - f_content is f_file with the relative pathname, initialized to NULL,
1185 - f_contqual is fully qualified f_file, assigned ONLY IF
1186   f_content nonNULL
1187 */
1188 file_ent = FALSE;
1189 f_content = NULL;
1190 f_contqual[0] = M_EOS;
1191
1192 /* check ENTITY and determine the figure type  */
1193 if (gentity)
1194     {
1195     m_lookent(gentity, &etype, &f_file, &wheredef);
1196     if (etype != M_SYSTEM)
1197         {
1198         M_WCHAR *wc_entsystem, *wc_entkw, *wc_stago, *wc_tagc;
1199
1200         wc_entsystem = MakeWideCharString(m_entsystem);
1201         wc_entkw = MakeWideCharString(m_entkw);
1202         wc_stago = MakeWideCharString(m_stago);
1203         wc_tagc = MakeWideCharString(m_tagc);
1204         m_err6(
1205             "%s not a %s %s, as required for the ENTITY parameter of %s%s%s",
1206                gentity,
1207                wc_entsystem,
1208                wc_entkw,
1209                wc_stago,
1210                m_parent(0),
1211                wc_tagc);
1212         m_free(wc_entsystem,"wide character string");
1213         m_free(wc_entkw,"wide character string");
1214         m_free(wc_stago,"wide character string");
1215         m_free(wc_tagc,"wide character string");
1216         }
1217     else
1218         {
1219         file_ent = TRUE;
1220         f_content = searchforfile(f_file);
1221         if (f_content)
1222             {
1223             if (getqualified(f_contqual, f_content))
1224                 {
1225                 /* unsuccessful qual */
1226                 if (w_strlen(f_content) < FNAMELEN)
1227                     w_strcpy(f_contqual, f_content);
1228                 else
1229                     {
1230                     m_err1("Internal error. File name too long: %s",
1231                            f_content);
1232                     m_exit(m_errexit);
1233                     }
1234                 }
1235             }
1236         else
1237             {
1238             m_err2("Can't find file %s (declared in entity %s)",
1239                    f_file,
1240                    gentity);
1241             }
1242         }
1243     if (!f_content) f_content = &empty;
1244
1245     mb_content = MakeMByteString(f_content);
1246     fprintf(outfile, " graphic %s", mb_content);
1247     m_free(mb_content,"multi-byte string");
1248     }
1249
1250 /* and the position now */
1251 if (gposition)
1252     {
1253     M_WCHAR *wc_left, *wc_right;
1254
1255     wc_left = MakeWideCharString(QLEFT);
1256     if (!m_wcupstrcmp(gposition, wc_left))
1257         {
1258         fputs(" gpos left", outfile);
1259         }
1260     else
1261         {
1262         wc_right = MakeWideCharString(QRIGHT);
1263         if (!m_wcupstrcmp(gposition, wc_right))
1264             {
1265             fputs(" gpos right", outfile);
1266             }
1267         else
1268             {
1269             m_err1("Invalid value for gposition: `%s'", gposition);
1270             }
1271         m_free(wc_right,"wide character string");
1272         }
1273     m_free(wc_left,"wide character string");
1274     }
1275
1276 /* end handling graphic specific code */
1277 /* handle link specific code */
1278 if (!glinktype)
1279     { /* default to type jump */
1280      /* do nothing */
1281     }
1282 else
1283     { /* type is set, choose which is correct */
1284     M_WCHAR *wc_stago, *wc_tagc;
1285
1286     if (!m_wcmbupstrcmp(glinktype, QJUMP))
1287         { fputs(" gtypelink 0", outfile); }
1288     else if (!m_wcmbupstrcmp(glinktype, QJUMPNEWVIEW))
1289         { fputs(" gtypelink 1", outfile); }
1290     else if (!m_wcmbupstrcmp(glinktype, QDEFINITION))
1291         { fputs(" gtypelink 2", outfile); }
1292     else if (!m_wcmbupstrcmp(glinktype, QEXECUTE))
1293         { fputs(" gtypelink 3", outfile); }
1294     else if (!m_wcmbupstrcmp(glinktype, QMAN))
1295         { fputs(" gtypelink 4", outfile); }
1296     else if (!m_wcmbupstrcmp(glinktype, QAPPDEFINED))
1297         { fputs(" gtypelink 5", outfile); }
1298     else
1299         { /* parser won't let this case happen */
1300         wc_stago = MakeWideCharString(m_stago);
1301         wc_tagc  = MakeWideCharString(m_tagc);
1302         m_err3(
1303           "%sLINK%s (glinktype=``%s'') did not match an allowed value",
1304               wc_stago,
1305               wc_tagc,
1306               glinktype); 
1307         m_free(wc_stago,"wide character string");
1308         m_free(wc_tagc,"wide character string");
1309         }
1310     }
1311
1312 if (ghyperlink)
1313     {
1314     char *mb_ghyperlink;
1315
1316     mb_ghyperlink = MakeMByteString(ghyperlink);
1317     fprintf(outfile, " glink \"%s\"", mb_ghyperlink);
1318     m_free(mb_ghyperlink,"multi-byte string");
1319     }
1320 else
1321     {
1322     if (glinktype || gdescription)
1323         {
1324         m_eprefix();
1325         fprintf(stderr,
1326                "Error: %sP%s ghyperlink was undefined.\n",
1327                m_stago,
1328                m_tagc);
1329         fprintf(m_errfile,
1330                "Error: %sP%s ghyperlink was undefined.\n",
1331                m_stago,
1332                m_tagc);
1333         fprintf(stderr,
1334     "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
1335                QJUMP,
1336                QJUMPNEWVIEW,
1337                QDEFINITION,
1338                QEXECUTE,
1339                QAPPDEFINED,
1340                QMAN);
1341         fprintf(m_errfile,
1342     "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
1343                QJUMP,
1344                QJUMPNEWVIEW,
1345                QDEFINITION,
1346                QEXECUTE,
1347                QAPPDEFINED,
1348                QMAN);
1349         m_errline("Use ``ghyperlink='' if the value contains non-alphabetics");
1350         m_esuffix();
1351         fputs(" glink _undefined", outfile);
1352         }
1353     }
1354
1355 if (gdescription)
1356     {
1357     fprintf(outfile, " description \"%s\"", gdescription);
1358     }
1359 /* end of link specific code */
1360 }
1361
1362 /* Process an item in a list */
1363 void item(id)
1364 M_WCHAR *id;
1365 {
1366 char orderString[32];
1367 static char *ROMAN0[] =
1368     {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
1369 static char *ROMAN10[] =
1370     {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
1371 static char *ROMAN100[] =
1372     {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
1373 static char ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1374 static char *roman0[] =
1375     {"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"};
1376 static char *roman10[] =
1377     {"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"};
1378 static char *roman100[] =
1379     {"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"};
1380 static char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
1381 static char numbers[] = "0123456789";
1382 int count, metaCount;
1383
1384 if (lastlist->lastlist->type == ORDER)
1385     fprintf(outfile, "<PARAGRAPH leftindent %d", ORDEREDLISTITEMINDENT);
1386 else
1387     fprintf(outfile, "<PARAGRAPH leftindent %d", LISTITEMINDENT);
1388
1389 if (lastlist->lastlist->space == TIGHT)
1390     {
1391     fputs(" after 0", outfile);
1392     }
1393 lastlist->lastlist->where = FIRST;
1394
1395 orderString[0] = '\0';
1396 count = ++lastlist->lastlist->count;
1397 if (count > 999) count = 999; /* holy cow!  Big list. */
1398 switch (lastlist->lastlist->order)
1399     {
1400     case UROMAN:
1401         strcpy(orderString, ROMAN100[count / 100]);
1402         strcat(orderString, ROMAN10[(count / 10) % 10]);
1403         strcat(orderString, ROMAN0[count % 10]);
1404         if ((count = strlen(orderString)) < 4)
1405             {
1406             char tmpString[32];
1407
1408             tmpString[0] = '\0';
1409             count = 4 - count;
1410             while (--count >= 0) strcat(tmpString, "\\ ");
1411             strcat(tmpString, orderString);
1412             strcpy(orderString, tmpString);
1413             }
1414         break;
1415     case UALPHA:
1416         metaCount = 1;
1417         while ((count -= 26) > 0) metaCount++;
1418         count = lastlist->lastlist->count;
1419         if (count > 999) count = 999;
1420         count -= 1;
1421         count %= 26;
1422         while (--metaCount >= 0) strncat(orderString, &ALPHABET[count], 1);
1423         break;
1424     case ARABIC:
1425         if (metaCount = (count / 100))
1426             strncat(orderString, &numbers[metaCount], 1);
1427         if (metaCount || ((count / 10) % 10))
1428             strncat(orderString, &numbers[(count / 10) % 10], 1);
1429         strncat(orderString, &numbers[count % 10], 1);
1430         break;
1431     case LROMAN:
1432         strcpy(orderString, roman100[count / 100]);
1433         strcat(orderString, roman10[(count / 10) % 10]);
1434         strcat(orderString, roman0[count % 10]);
1435         if ((count = strlen(orderString)) < 4)
1436             {
1437             char tmpString[32];
1438
1439             tmpString[0] = '\0';
1440             count = 4 - count;
1441             while (--count >= 0) strcat(tmpString, "\\ ");
1442             strcat(tmpString, orderString);
1443             strcpy(orderString, tmpString);
1444             }
1445         break;
1446     case LALPHA:
1447         metaCount = 1;
1448         while ((count -= 26) > 0) metaCount++;
1449         count = lastlist->lastlist->count;
1450         if (count > 999) count = 999;
1451         count -= 1;
1452         count %= 26;
1453         while (--metaCount >= 0) strncat(orderString, &alphabet[count], 1);
1454         break;
1455     }
1456
1457 if (lastlist->lastlist->type == ORDER)
1458     {
1459     fprintf( /* keep the '('s balanced */
1460             outfile,
1461             "><LABEL><WEIGHT bold>%s%2s%c</WEIGHT></LABEL",
1462             (strlen(orderString) > 1) ? "" : "\\",
1463             orderString,
1464             lastlist->lastlist->punct == DOTPUNCT ? '.' : ')' );
1465     if (id)
1466         {
1467         char buffer[400], *mbyte;
1468         M_WCHAR *wc;
1469
1470         sprintf(buffer, "Item %s", orderString);
1471         wc = MakeWideCharString(buffer);
1472         w_strcpy(xrefstring, wc);
1473         m_free(wc,"wide character string");
1474
1475         xstrlen = w_strlen(xrefstring);
1476         m_getline(&xrffile, &xrfline);
1477         if (xrffile == NULL)
1478             {
1479             /* set to primary input */
1480             xrffile = inputname;
1481             }
1482
1483         setid(id,
1484              TRUE,
1485              FALSE,
1486              inchapter,
1487              chapstring,
1488              xrffile,
1489              xrfline, TRUE);
1490
1491         mbyte = MakeMByteString(id);
1492         fprintf(outfile, " id \"%s\"", id);
1493         m_free(mbyte,"multi-byte string");
1494         }
1495     }
1496 else
1497     { /* Bullet, Check or Plain list */
1498     if (id) m_error("Cross-reference ID in non-ORDER list not allowed");
1499     if (lastlist->lastlist->type == BULLET)
1500         {
1501         fprintf(outfile,
1502                 "><LABEL><CHARACTERSET symbol>%c</></LABEL",
1503                 183 /* BULLET CHAR */ );
1504         }
1505     else if (lastlist->lastlist->type == CHECK)
1506         {
1507         /* no hollow square in the symbol charset, use hollow diamond */
1508         fprintf(outfile,
1509                 "><LABEL><CHARACTERSET symbol>%c</></LABEL",
1510                 224 /* CHECK CHAR */ );
1511         }
1512     else /* if ( lastlist->lastlist->type == PLAIN) */
1513         { /* above commented out to make this the default for MILSPEC lists */
1514         /* emit a hard space label to make things look right when TIGHT */
1515         fprintf(outfile, "><LABEL>\\ </LABEL");
1516         }
1517     }
1518 fputs(">\n", outfile);
1519 }
1520
1521
1522 /* Express a sequence number as a letter in an alpha list or appendix */
1523 #if defined(M_PROTO)
1524 void itoletter(int n, char start, char *dest, int length)
1525 #else
1526 void itoletter(n, start, dest, length)
1527 int n;
1528 char start;
1529 char *dest;
1530 int length;
1531 #endif
1532 {
1533 char invert[10];
1534 char *p, *q;
1535
1536 if (n <=0)
1537     {
1538     m_error("Internal error: converting non-positive number to letter");
1539     dest[0] = start;
1540     dest[1] = M_EOS;
1541     return;
1542     }
1543 for (p = invert; n ; p++, n = (n - 1) / 26)
1544     {
1545     *p = start + (n - 1) % 26;
1546     if (p == &invert[length] || p == &invert[sizeof(invert)])
1547         {
1548         m_error("Internal error: out of space converting number to letter");
1549         break;
1550         }
1551     }
1552 p--;
1553 q = dest;
1554 while (TRUE)
1555     {
1556     *q++ = *p;
1557     if (p == invert) break;
1558     p--;
1559     };
1560 *q = M_EOS;
1561 }
1562
1563 /* Start the <MANUAL> tag processing */
1564 void manustart(language, idxvol, status)
1565 M_WCHAR *language, *idxvol, *status;
1566 {
1567 if (idxvol) w_strcpy(volume, idxvol);
1568 }  /* END manustart procedure */
1569
1570
1571 /* Issue error message and text in document element is not supported in
1572    a particular option or context */
1573 void notimp(eltname, option)
1574 char *eltname;
1575 char *option;
1576 {
1577 char *p;
1578 M_WCHAR *wc_stago, *wc_eltname, *wc_tagc, *wc_option;
1579
1580 fputs("<PARAGRAPH><WEIGHT bold>", outfile);
1581 for (p = m_stago; *p ; p++)
1582     {
1583     outchar(*p, outfile);
1584     }
1585 fputs(eltname, outfile);
1586 for (p = m_tagc; *p ; p++)
1587     {
1588     outchar(*p, outfile);
1589     }
1590 fprintf(outfile, " not supported in %s.</WEIGHT></PARAGRAPH>\n\n", option);
1591
1592 wc_stago = MakeWideCharString(m_stago);
1593 wc_eltname = MakeWideCharString(eltname);
1594 wc_tagc = MakeWideCharString(m_tagc);
1595 wc_option = MakeWideCharString(option);
1596
1597 m_err4("%s%s%s not suppported in %s",
1598        wc_stago,
1599        wc_eltname,
1600        wc_tagc,
1601        wc_option);
1602
1603 m_free(wc_stago,"wide character string");
1604 m_free(wc_eltname,"wide character string");
1605 m_free(wc_tagc,"wide character string");
1606 m_free(wc_option,"wide character string");
1607
1608 outfile = nullfile;
1609 }
1610
1611 /* Close current output, construct new output name and open output */
1612 void open_new_helpfile()
1613 {        
1614 int j, length;
1615 char htfilenostring[15];
1616 M_WCHAR *wc_1, *wc_2;
1617
1618 if (! firstnode)
1619     {
1620     fputs("</TOPIC>\n", outfile);
1621     }
1622 fclose(m_outfile);
1623
1624 m_itoa(htfileno++, htfilenostring);
1625
1626 if ((j = strlen(htfilenostring)) > PRE_EXTENSION_LIMIT)
1627     {
1628     helptmpbuf[0] = '0' + PRE_EXTENSION_LIMIT;
1629     helptmpbuf[1] = '\0';
1630     wc_1 = MakeWideCharString(htfilenostring);
1631     wc_2 = MakeWideCharString(helptmpbuf);
1632     m_err2(
1633     "Error:  Tail of new output help file, `%s', is longer than %s characters",
1634            wc_1,
1635            wc_2);
1636     m_free(wc_1,"wide character string");
1637     m_free(wc_2,"wide character string");
1638     m_exit(m_errexit);
1639     }
1640
1641 switch(j)
1642     {
1643     case 0: m_error("Fatal Error: Null tail on new help file.");
1644         m_exit(m_errexit);
1645         break;
1646     case 1:
1647         *helpext = '0';
1648         *(helpext + 1) = *htfilenostring;
1649         *(helpext + 2) = '\0';
1650         break;
1651     case 2:
1652           *helpext = htfilenostring[0];
1653           *(helpext + 1) = htfilenostring[1];
1654           *(helpext + 2) = '\0';
1655           break;
1656     default:
1657           m_error("Internal error. (helpext)");
1658           break;
1659     }
1660
1661 strcat(helpext, ".ht");
1662 m_openchk(&m_outfile, helpbase, "w");
1663 outfile = m_outfile;
1664 firstnode = TRUE;
1665
1666 /* keep name for logging id's */
1667 m_free(savehelpfilename, "help file name");
1668 length = strlen(helpbase) + 1;
1669 savehelpfilename = (M_WCHAR *) m_malloc(length, "help file name");
1670 mbstowcs(savehelpfilename, helpbase, length);
1671
1672 } /* end procedure open_new_helpfile */
1673
1674
1675 /* Verify that val will be understandable to TeX as a dimension */
1676 M_WCHAR *okdimen ( val )
1677 M_WCHAR *val;
1678 {
1679 /* returns val if a valid TeX dimension, else NULL */
1680 char s1[M_NAMELEN + 1], s2[M_NAMELEN + 1];
1681 float flt;
1682 int i;
1683 M_WCHAR *valid = NULL;
1684 char *mbyte;
1685
1686 if ( val == NULL ) return ( NULL );
1687
1688 mbyte = MakeMByteString(val);
1689
1690 if (sscanf(mbyte, "%f%s%s", &flt, s1, s2) == 2)
1691     for (i = 0; i < (sizeof(dimarray) / sizeof(char *)); ++i)
1692         if (! m_mbmbupstrcmp(dimarray[i], s1))
1693             {
1694             valid = val;
1695             break;
1696             }
1697 m_free(mbyte,"multi-byte string");
1698 return (valid);
1699 }  /* END procedure okdimen  */
1700
1701
1702 /* Start a rsect */
1703 void rsectstart(id, pagebreak)
1704 M_WCHAR *id, *pagebreak;
1705 {
1706 savid = checkid(id);
1707 iderr = FALSE;
1708 if (rsectseq)
1709     {
1710     M_WCHAR *wc_samepage;
1711
1712     wc_samepage = MakeWideCharString(QSAMEPAGE);
1713     if (pagebreak &&
1714         (rsectsame != (LOGICAL) (! m_wcupstrcmp(pagebreak,wc_samepage))))
1715         {
1716         m_err1(
1717           "%s specification ignored within a sequence of reference sections",
1718                pagebreak);
1719         }
1720     m_free(wc_samepage,"wide character string");
1721     if (rsectholdnew)
1722         {
1723         rsectholdnew = FALSE;
1724         }
1725     }
1726 else
1727     {
1728     rsectsame = (LOGICAL) (vrsectpage(pagebreak) == SAMEPAGE);
1729     rsectseq = TRUE;
1730     rsectholdnew = FALSE;
1731     }
1732
1733 if (rsectsame && m_mblevel("S3")) st4 = TRUE;
1734 didabbrev = FALSE;
1735 if (! rsectsame)
1736     {  /* Finish off NEED BEGIN if necessary */
1737     if (m_mblevel("S3")) {}
1738     else if (m_mblevel("S2")) {}
1739     else if (m_mblevel("S1")) {}
1740     /* rsect in TEST shares the same level head as S1 */
1741     else if (m_mblevel("TEST")) {}
1742     else {}
1743     }
1744 else if (m_mblevel("S3")) {}
1745 else if (m_mblevel("S2")) {}
1746 else if (m_mblevel("S1")) {}
1747 /* rsect in TEST shares the same level head as S1 */
1748             else if (m_mblevel("TEST")) {}
1749 /* two cases for rsect SAMEPAGE in chapters */
1750 else if (chapst) {}
1751 else /* rsect SAMEPAGE is first element in chapter, suppress rule */
1752     {}
1753 chapst = TRUE;
1754 }  /* END procedure rsectstart  */
1755
1756
1757 /* Called at the end of a chapter, appendix, or section to end an open
1758    sequence of rsects */
1759 void rseqend(M_NOPAR)
1760 {
1761 if (rsectseq)
1762     {
1763     rsectseq = FALSE;
1764     rshnewclear();
1765     }
1766 }
1767
1768 /* Rsectholdnew clear -- have determined a <newpage> in a samepage <rsect>
1769    sequence is not immediately followed by a new <rsect>.  Hence can output
1770    the \newpage macro call without concern about side effects on the
1771    page header */
1772 void rshnewclear(M_NOPAR)
1773 {
1774 if (rsectholdnew)
1775     {
1776     rsectholdnew = FALSE;
1777     }
1778 }
1779
1780 /* Follow search path to find a file, returning qualified name */
1781 M_WCHAR *searchforfile(file)
1782 M_WCHAR *file;
1783 {
1784 M_WCHAR *filename;
1785 SEARCH  *searchp;
1786 char    *mb_file, mb_filename[2048];
1787 int     dir_leng,file_leng;
1788
1789 mb_file = MakeMByteString(file);
1790 if (! access(mb_file, READABLE))
1791     {
1792     filename = (M_WCHAR *)
1793         m_malloc(w_strlen(file) + 1, "figure/icon filename");
1794     w_strcpy(filename, file);
1795     m_free(mb_file,"multi-byte string");
1796     return(filename);
1797     }
1798
1799 file_leng = strlen(mb_file);
1800 for (searchp = path; searchp ; searchp = searchp->next)
1801     {
1802     if (((dir_leng = strlen(searchp->directory)) + file_leng) >= 2048)
1803         {
1804         M_WCHAR *wc;
1805
1806         wc = MakeWideCharString(searchp->directory);
1807         m_err2("%s and %s overflow the file name space", wc, file);
1808         m_free(wc,"wide character string");
1809         continue;
1810         }
1811     strcpy(mb_filename, searchp->directory);
1812     strcpy(mb_filename+dir_leng, mb_file);
1813     if (! access(mb_filename, READABLE))
1814         {
1815         m_free(mb_file,"multi-byte string");
1816         return(MakeWideCharString(mb_filename));
1817         }
1818     }
1819
1820 m_free(mb_file,"multi-byte string");
1821 return(NULL);
1822 }
1823
1824
1825 /* show how much memory is available */
1826 void showmemavail(M_NOPAR)
1827 {
1828 int amount=0;
1829 char *p;
1830
1831 while (p = (char *) malloc(1024))
1832     {
1833     amount += 1;
1834     if ( amount >= 512 ) break;
1835     }
1836 m_exit(0);
1837 }
1838
1839 /* Start a new helpnode */
1840 #if defined(M_PROTO)
1841 void starthelpnode(M_WCHAR *id, LOGICAL suppress_topic_map)
1842 #else
1843 void starthelpnode(id, suppress_topic_map)
1844 M_WCHAR *id;
1845 LOGICAL suppress_topic_map;          /* should we suppress .tpc entry */
1846 #endif
1847 {
1848 int i;
1849 char *mbyte;
1850 char mb_nodeid[NODEID_LENGTH+1], nodenum[32];
1851
1852 if (firstnode)
1853     {
1854     /* don't end nonexistent previous node */
1855     firstnode = FALSE;
1856     }
1857 else
1858     {
1859     fprintf(outfile, "</TOPIC>\n\n");
1860     }
1861
1862 if (outfile != m_outfile)
1863     {
1864     m_error("Internal warning:  Outfile has been redirected.");
1865     m_errcnt--;
1866     }
1867
1868 fflush(m_outfile);
1869 nodeoffset = ftell(m_outfile);
1870
1871 mbyte = MakeMByteString(helpcharset);
1872 fprintf(outfile, "<TOPIC charset %s>\n", mbyte);
1873 m_free(mbyte,"multi-byte string");
1874
1875 if (nodeoffset == -1L)
1876     {
1877     m_error("Internal error, node offset.");
1878     m_exit(m_errexit);
1879     }
1880
1881 if (id == NULL)
1882     {
1883     strcpy(mb_nodeid, "_TOPIC_ID_");
1884     m_itoa(autonodenumber, nodenum);
1885     strcpy(nodestring, nodenum);
1886     autonodenumber++;
1887     strcat(mb_nodeid, nodenum);
1888     mbstowcs(nodeid, mb_nodeid, NODEID_LENGTH);
1889     }
1890 else
1891     {
1892     w_strncpy(nodeid, id, NODEID_LENGTH);
1893     wcstombs(mb_nodeid, id, NODEID_LENGTH);
1894     }
1895
1896 /*     fprintf(stderr, "Starting Node ID: %s\n", nodeid); */
1897 mbyte = MakeMByteString(savehelpfilename);
1898 fprintf(idtablefp, "%s: %s %ld\n", mb_nodeid, mbyte, nodeoffset);
1899 m_free(mbyte,"multi-byte string");
1900
1901 if (!suppress_topic_map)
1902     {
1903     /* handle TOPIC MAP file */
1904
1905     if (thisnodelevel == lastnodelevel)
1906         { /* this node at same level */
1907         if (!isfirsttopicmap)
1908             {
1909             fputs("\n", topicmapfp);
1910             }
1911         else
1912             {
1913             isfirsttopicmap = FALSE;
1914             }
1915         /* indent routine >here< */
1916         for (i = thisnodelevel; --i >= 0;) { fputs("  ", topicmapfp); }
1917         fprintf(topicmapfp, "%s", mb_nodeid);
1918         }
1919     /* elseif */
1920     if (thisnodelevel > lastnodelevel)
1921         { /* this node is deeper */
1922         fputs(" {\n", topicmapfp);  /* keep the '}' balanced */
1923         /* indent routine >here< */
1924         for (i = thisnodelevel; --i >= 0;) { fputs("  ", topicmapfp); }
1925         fprintf(topicmapfp, "%s", mb_nodeid);
1926         }
1927     /* else */
1928     if (thisnodelevel < lastnodelevel)
1929         { /* this node is higher */
1930         fputs("\n", topicmapfp);
1931         while (thisnodelevel != lastnodelevel--)
1932             {
1933             /* indent routine >here< */
1934             for (i = lastnodelevel; --i >= 0;) { fputs("  ", topicmapfp); }
1935             /* keep the '{' balanced */
1936             fputs("}\n", topicmapfp);
1937             }
1938         for (i = thisnodelevel; --i >= 0;) { fputs("  ", topicmapfp); }
1939         fprintf(topicmapfp, "%s", mb_nodeid);
1940         }
1941     /* get ready for next time */
1942     lastnodelevel = thisnodelevel;
1943     }
1944 } /* End starthelpnode(id) */
1945
1946
1947 #if defined(M_PROTO)
1948 void mb_starthelpnode(char *id, LOGICAL suppress_topic_map)
1949 #else
1950 void mb_starthelpnode(id, suppress_topic_map)
1951 char *id;
1952 LOGICAL suppress_topic_map;          /* should we suppress .tpc entry */
1953 #endif
1954 {
1955 M_WCHAR *wc;
1956
1957 wc = MakeWideCharString(id);
1958 starthelpnode(wc, suppress_topic_map);
1959 m_free(wc,"wide character string");
1960 }
1961
1962
1963 /* Start a labeled list */
1964 void startlablist(longlabel, width, spacing)
1965 M_WCHAR *longlabel, *width, *spacing;
1966 {
1967 STARTSTUFF;
1968 rshnewclear();
1969 list++;
1970 if (list > MAXLISTLEV)
1971     m_error("Nesting of <LIST> and <LABLIST> too deep");
1972 fputs("<PARAGRAPH>\n", outfile);
1973 if (list <= MAXLISTLEV)
1974     {
1975     if (vspacing(spacing) == TIGHT)
1976         {
1977         lablistindented[list] = TRUE;
1978         }
1979     else
1980         {
1981         lablistindented[list] = FALSE;
1982         }
1983     }
1984 }
1985
1986 /* Start a list */
1987 void startlist(type, order, spacing, cont)
1988 M_WCHAR *type, *order, *spacing, *cont;
1989 {
1990 LIST *nextlist;
1991 CONTCHAIN *chain;
1992 CONTCHAIN *xchain;
1993 M_WCHAR *wc;
1994
1995 STARTSTUFF;
1996 rshnewclear();
1997 list++;
1998
1999 /* Set ``paragraph'' for a new list */
2000 if (type && !m_wcmbupstrcmp(type, QORDER))
2001     fprintf(outfile,
2002             "<PARAGRAPH firstindent %d leftindent %d>\n",
2003             ORDEREDLISTFIRSTINDENT,
2004             ORDEREDLISTFIRSTINDENT);
2005 else
2006     fprintf(outfile,
2007             "<PARAGRAPH firstindent %d leftindent %d>\n",
2008             LISTFIRSTINDENT,
2009             LISTFIRSTINDENT);
2010
2011 if (list > MAXLISTLEV)
2012     m_error("Nesting of <LIST> and <LABLIST> too deep");
2013
2014 if (! lastlist->started && cont)
2015     {
2016     m_error("No previous list to continue");
2017     cont = NULL;
2018     }
2019
2020 if (cont)
2021     {
2022     if (order && (vordertype(order) != lastlist->order))
2023         {
2024         m_error("Unable to continue a list and change the numbering scheme");
2025         cont = NULL;
2026         }
2027
2028     if (type && (vtype(type) != lastlist->type))
2029         {
2030         m_error("Unable to continue a list and change its type");
2031         cont = NULL;
2032         }
2033     }
2034
2035 if (! cont)
2036     { /* clear old list? */
2037     for (chain = lastlist->chain; chain ; chain = xchain)
2038         {
2039         xchain = chain->next;
2040         m_free(chain, "list chain");
2041         }
2042     lastlist->chain = NULL;
2043     lastlist->count = 0;
2044     }
2045
2046 /* If outermost list, initialize according to current defaults */
2047 if (! cont && lastlist == &outlist)
2048     {
2049     outlist.type       = vtype(NULL);
2050     outlist.order      = vordertype(NULL);
2051     outlist.count      = 0;
2052     outlist.space      = vspacing(NULL);
2053     outlist.punct      = DOTPUNCT;
2054     }
2055
2056 if (type) lastlist->type = vtype(type);
2057
2058 if (order)
2059     {
2060     lastlist->type = ORDER;
2061     lastlist->order = vordertype(order);
2062     }
2063
2064 if (spacing && ! m_wcmbupstrcmp(spacing, QTIGHT)) lastlist->space = TIGHT;
2065
2066 if (type && order && m_wcmbupstrcmp(type, QORDER))
2067   m_err2("Incompatible specification for list: %s and %s", type, order);
2068
2069 if (lastlist->type == ORDER)
2070     {
2071     if (lastlist->order == ARABIC) {}
2072     else if (lastlist->order == UROMAN) {}
2073     else if (lastlist->order == LROMAN) {}
2074     else if (lastlist->order == UALPHA) {}
2075     else /* if (lastlist->order == LALPHA) */  {}
2076     chain = (CONTCHAIN *) m_malloc(sizeof(CONTCHAIN), "list chain");
2077     chain->next = lastlist->chain;
2078     lastlist->chain = chain;
2079     chain->where = ftell(outfile);
2080     }
2081
2082 if (lastlist->type == PLAIN) {}
2083 else if (lastlist->type == BULLET) {}
2084 else if (lastlist->type == CHECK) {}
2085 lastlist->started = TRUE;
2086
2087 /* Prepare for sublist */
2088 nextlist = (LIST *) m_malloc(sizeof(LIST), "list structure");
2089 nextlist->lastlist = lastlist;
2090 nextlist->type = lastlist->type;
2091 nextlist->punct = lastlist->punct;
2092 if (lastlist->type == ORDER)
2093     {
2094     nextlist->order = lastlist->order + 1;
2095     if (nextlist->order > LROMAN)
2096         {
2097         nextlist->order = ARABIC;
2098         nextlist->punct = PARENPUNCT;
2099         }
2100     }
2101 else nextlist->order = lastlist->order;
2102 nextlist->count = 0;
2103 nextlist->space = lastlist->space;
2104 nextlist->started = FALSE;
2105 nextlist->where = FIRST;
2106 nextlist->chain = NULL;
2107 lastlist = nextlist;
2108 }
2109
2110
2111 /* Test for a comment at the beginning of the input document to indicate
2112    whether the file is a generated index.  If so, set MARKUP e option. */
2113 void testindexfile(first)
2114 FILE *first;
2115 {
2116 char *p;
2117 int c;
2118
2119 for (p = m_mdo; *p ; p++)
2120     {
2121     c = getc(first);
2122     if (c !=*p) return;
2123     }
2124
2125 for (p = m_comment; *p ; p++)
2126     {
2127     c = getc(first);
2128     if (c !=*p) return;
2129     }
2130
2131 for (p = "Index"; *p ; p++)
2132     {
2133     c = getc(first);
2134     if (c !=*p) return;
2135     }
2136
2137 m_entdupchk = FALSE;
2138 }
2139
2140 /* Open and initialize TeX file */
2141 void texinit(M_NOPAR)
2142 {
2143 LOGICAL init = TRUE;
2144 unsigned char type;
2145 M_WCHAR *content;
2146 unsigned char wheredef;
2147 M_WCHAR *name;
2148 M_WCHAR *qfile;
2149 LOGICAL icon;
2150 SEARCH *searchp;
2151 char *p;
2152 int ic;
2153 int i;
2154 M_WCHAR wbs, wsl, wcl;
2155 M_WCHAR *wc;
2156
2157 /* Check .XRF file */
2158 strcpy(helpext, ".xrh");
2159 xrf = fopen(helpbase, "r");
2160 if (! xrf) rebuild = TRUE;
2161 else
2162     {
2163     fscanf(xrf, "\\gobble\001");
2164     for (p = m_signon; *p ; p++)
2165         {
2166         ic = getc(xrf);
2167         if (ic != (int) *p)
2168             {
2169             m_errline(
2170         "Output files from different version of Tag, regenerating. . .\n");
2171             fclose(xrf);
2172             xrf = NULL;
2173             rebuild = TRUE;
2174             break;
2175             }
2176         }
2177     }
2178 if (xrf)
2179     while ((ic = getc(xrf)) != EOF)
2180         if (ic == '\n') break;
2181 if (xrf && ic !=EOF)
2182     while ((ic = getc(xrf)) != EOF)
2183         if (ic == '\n') break;
2184
2185 rebuild = TRUE;
2186
2187 /* Open output files */
2188 strcpy(helpext, "00"); /* first file starts at 00 */
2189 strcat(helpext, ".ht");
2190 m_openchk(&m_outfile, helpbase, "w");
2191 outfile = m_outfile;
2192 firstnode = TRUE;
2193
2194 savehelpfilename = (M_WCHAR *)m_malloc(strlen(helpbase)+1, "help file name");
2195 mbstowcs(savehelpfilename, helpbase, strlen(helpbase) + 1);
2196
2197 /* doc reg file */
2198
2199 strcpy(helpext, ".hmi");
2200 m_openchk(&docregfp, helpbase, "w");
2201
2202
2203 /* id table file */
2204 strcpy(helpext, ".idt");
2205 m_openchk(&idtablefp, helpbase, "wb");
2206
2207 /* topic map file */
2208 strcpy(helpext, ".tpc");
2209 m_openchk(&topicmapfp, helpbase, "wb");
2210
2211 /* Index file */
2212 strcpy(helpext, ".idx");
2213 m_openchk(&indexfp, helpbase, "wb");
2214
2215 /* Sign-on message passed to TeX and generated files. */
2216 /* EXACT FORMAT AND ORDER OF INITIALIZATION PARAMETERS IN .TEX FILE
2217 IS CHECKED DURING TESTING FOR NEED TO REGENERATE .TEX FILE.  */
2218 texcomplete = ftell(outfile);
2219
2220 while (name = m_cyclent(init, &type, &content, &wheredef))
2221     {
2222     init = FALSE;
2223     qfile = NULL;
2224     icon = FALSE;
2225
2226     if (type == M_SYSTEM)
2227         qfile = searchforfile(content);
2228
2229     if (qfile) m_free(qfile, "figure filename");
2230
2231     if (type == M_SYSTEM)
2232         {
2233         mbtowc(&wbs, "\\", 1);
2234         mbtowc(&wsl, "/", 1);
2235         mbtowc(&wcl, ":", 1);
2236
2237         if (w_strchr(content, wbs) ||
2238             w_strchr(content, wsl) ||
2239             w_strchr(content, wcl) )
2240             {
2241             m_err2("Avoid directory names in FILE entity %s: %s",
2242                    name,
2243                    content);
2244             m_errline("(Use the SEARCH option instead)\n");
2245             }
2246         }
2247     }
2248
2249 #if defined(MSDOS)
2250 m_openchk(&nullfile, "NUL", "w");
2251 #else
2252 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
2253 m_openchk(&nullfile, "/dev/null", "w");
2254 #else
2255 m_openchk(&nullfile, "nullfile", "w");
2256 #endif
2257 #endif
2258 #if defined(MSDOS)
2259 #else
2260 #endif
2261
2262 idxupdate = ftell(outfile);
2263
2264 /* Include cross-reference file */
2265 strcpy(helpext, ".xrh");
2266 loadxref();
2267 postpreamble = ftell(outfile);
2268 }
2269
2270 /* Issue error message and text in document when starting an unimplemented
2271    element */
2272 void mb_unimp(eltname)
2273 char *eltname;
2274 {
2275 M_WCHAR *wc_stago, *wc_eltname, *wc_tagc;
2276 #if 0
2277 char *p;
2278
2279 fputs("<PARAGRAPH><WEIGHT bold>", outfile);
2280 for (p = m_stago; *p ; p++)
2281     {
2282     outchar(*p, outfile);
2283     }
2284 fputs(eltname, outfile);
2285 for (p = m_tagc; *p ; p++)
2286     {
2287     outchar(*p, outfile);
2288     }
2289 fprintf(outfile, " not implemented for HelpTag. </WEIGHT></PARAGRAPH>\n\n");
2290 #endif /* 0 */
2291
2292 wc_stago   = MakeWideCharString(m_stago);
2293 wc_eltname = MakeWideCharString(eltname);
2294 wc_tagc    = MakeWideCharString(m_tagc);
2295
2296 m_err3("%s%s%s is not implemented for HelpTag", wc_stago, wc_eltname, wc_tagc);
2297
2298 m_free(wc_stago,"wide character string");
2299 m_free(wc_eltname,"wide character string");
2300 m_free(wc_tagc,"wide character string");
2301 }
2302
2303
2304 void unimp(eltname)
2305 M_WCHAR *eltname;
2306 {
2307 char *mb_eltname;
2308
2309 mb_eltname = MakeMByteString(eltname);
2310 mb_unimp(mb_eltname);
2311 m_free(mb_eltname,"multi-byte string");
2312 }
2313
2314
2315 /* convert user-supplied dimension to scaled points */
2316 long usertosp(s)
2317 char *s;
2318 {
2319 double num = 0.0, num2 = 0.0;
2320 int i;
2321 char temp[8];
2322
2323 temp[0] = M_EOS;
2324 if (sscanf(s,"%lf%s%lf",&num, temp, &num2) == 3)
2325     { /* get numeric portion */
2326     M_WCHAR *wc_s, *wc_temp;
2327
2328     wc_s = MakeWideCharString(s);
2329     wc_temp = MakeWideCharString(temp);
2330     m_err2("%s: Ignoring number after %s in Tag dimension", wc_s, wc_temp);
2331     m_free(wc_s,"wide character string");
2332     m_free(wc_temp,"wide character string");
2333     }
2334
2335 i=0;
2336 while (temp[i] != M_EOS)
2337     {
2338     if (isupper(temp[i])) temp[i] = tolower(temp[i]);
2339     i++;
2340     }
2341
2342 if (! m_mbmbupstrcmp(temp, "IN"))
2343     num *= PTperIN * SPperPT;
2344 else if (! m_mbmbupstrcmp(temp, "CM"))
2345     num *= PTperIN / CMperIN * SPperPT;
2346 else if (! m_mbmbupstrcmp(temp,"MM"))
2347     num *= PTperIN / MMperIN * SPperPT;
2348 else if (! m_mbmbupstrcmp(temp, "PC"))
2349     num *= PTperPC * SPperPT;
2350 else if (! m_mbmbupstrcmp(temp,"PT"))
2351     num *= SPperPT;
2352 else
2353     m_error("Invalid units: pt assumed");
2354
2355 if (num<0.0)
2356     {
2357     m_error("No negative dimensions: positive assumed");
2358     num *= -1.0;
2359     }
2360 return((long) num );
2361 }
2362
2363 /* Lookup localized header string entity as defined (by default) in
2364    locallang.ent.  If the the header string was not found, or it was
2365    not of type "desiredType", return the default.
2366
2367    If the entity is of type file (M_SYSTEM) then if the content is not
2368    empty search the path for the file.  If the file is found, return
2369    its name else return an empty string.
2370
2371    If this routine returns anything other than the empty string (""),
2372    the string returned must be m_free'd.
2373 */
2374 char *
2375 #if defined(M_PROTO)
2376 GetDefaultHeaderString(
2377     char          *elementName,
2378     unsigned char  desiredType,
2379     char          *defaultString )
2380 #else
2381 GetDefaultHeaderString(elementName, desiredType, defaultString)
2382 char          *elementName;
2383 unsigned char  desiredType;
2384 char          *defaultString;
2385 #endif
2386 {
2387 unsigned char type,wheredef;
2388 M_WCHAR *content;
2389 M_WCHAR *path;
2390 M_WCHAR *wc_elementName;
2391 char    *mb_content;
2392 char    *retval;
2393
2394 wc_elementName = MakeWideCharString(elementName);
2395 if (m_lookent(wc_elementName, &type, &content, &wheredef))
2396     {
2397     if (type == desiredType)
2398         {
2399         if (type == M_SDATA)
2400             {
2401             m_free(wc_elementName,"wide character string");
2402             mb_content = MakeMByteString(content);
2403             if (!*mb_content)
2404                 {
2405                 m_free(mb_content,"multi-byte string");
2406                 return "";
2407                 }
2408             else
2409                 return mb_content;
2410             }
2411         if (*content)
2412             {
2413             path = searchforfile(content);
2414             if (!path)
2415                 {
2416                 m_err2("Can't find file %s (declared in entity %s)",
2417                        content,
2418                        wc_elementName);
2419                 m_free(wc_elementName,"wide character string");
2420                 return("");
2421                 }
2422             else
2423                 {
2424                 m_free(wc_elementName,"wide character string");
2425                 return MakeMByteString(path);
2426                 }
2427             }
2428         m_free(wc_elementName,"wide character string");
2429         return "";
2430         }
2431     }
2432
2433 m_free(wc_elementName,"wide character string");
2434 if (*defaultString)
2435     {
2436     retval = m_malloc(strlen(defaultString) + 1,
2437                       "GetDefaultHeaderString return");
2438     return strcpy(retval, defaultString);
2439     }
2440
2441 return "";
2442 }
2443
2444
2445 /*
2446  * Look for an entity by the name of "LanguageElementDefaultLocale".
2447  * If found, set the current locale to be the content of that entity.
2448 */
2449 void
2450 SetDefaultLocale()
2451 {
2452 unsigned char type,wheredef;
2453 M_WCHAR *elementName;
2454 M_WCHAR *content;
2455 char    *mb_content;
2456
2457 elementName = MakeWideCharString("LanguageElementDefaultLocale");
2458 if (m_lookent(elementName, &type, &content, &wheredef))
2459     {
2460     if (type == M_SDATA)
2461         {
2462         mb_content = MakeMByteString(content);
2463         setlocale(LC_ALL, mb_content);
2464         m_free(mb_content,"multi-byte string");
2465         }
2466     else
2467         setlocale(LC_ALL, "");
2468     }
2469 else
2470     setlocale(LC_ALL, "");
2471 m_free(elementName,"wide character string");
2472
2473 elementName = MakeWideCharString("LanguageElementDefaultCharset");
2474 if (m_lookent(elementName, &type, &content, &wheredef))
2475     {
2476     if (type == M_SDATA)
2477         {
2478         m_free(helpcharset, "help charset");
2479         helpcharset = m_malloc(w_strlen(content) + 1, "help charset");
2480         w_strcpy(helpcharset, content);
2481         }
2482     }
2483 m_free(elementName,"wide character string");
2484 }
2485
2486
2487 #if defined(M_PROTO)
2488 void paragraph(M_WCHAR *indent,
2489                M_WCHAR *id,
2490                M_WCHAR *gentity,
2491                M_WCHAR *gposition,
2492                M_WCHAR *ghyperlink,
2493                M_WCHAR *glinktype,
2494                M_WCHAR *gdescription,
2495                char    *listinfo)
2496 #else
2497 void paragraph(indent,
2498                id,
2499                gentity,
2500                gposition,
2501                ghyperlink,
2502                glinktype,
2503                gdescription,
2504                listinfo)
2505 M_WCHAR *indent;
2506 M_WCHAR *id;
2507 M_WCHAR *gentity;
2508 M_WCHAR *gposition;
2509 M_WCHAR *ghyperlink;
2510 M_WCHAR *glinktype;
2511 M_WCHAR *gdescription;
2512 char    *listinfo;
2513 #endif
2514 {
2515 if (id)
2516     {
2517     mbstowcs(xrefstring, "\\<xref paragraph>", 400);
2518     xstrlen = w_strlen(xrefstring);
2519     m_getline(&xrffile, &xrfline);
2520     if (xrffile == NULL)
2521         {
2522         /* set to primary input source */
2523         xrffile = inputname;
2524         }
2525     setid(id, TRUE, FALSE, inchapter, chapstring, xrffile, xrfline, FALSE);
2526
2527     {
2528     char *mb_nodeid, *mb_id;
2529
2530     mb_nodeid = MakeMByteString(nodeid);
2531     mb_id     = MakeMByteString(id);
2532     fprintf(idtablefp, "%s> %s\n", mb_nodeid, mb_id);
2533     m_free(mb_nodeid,"multi-byte string");
2534     m_free(mb_id,"multi-byte string");
2535     }
2536
2537     }
2538 chapst = TRUE;
2539 rshnewclear();
2540 fputs("<PARAGRAPH", outfile);
2541 if (id)
2542     {
2543     char *mb_id;
2544
2545     mb_id = MakeMByteString(id);
2546     fprintf(outfile, " id %s", mb_id);
2547     m_free(mb_id,"multi-byte string");
2548     }
2549
2550 if (st4) st4 = FALSE;
2551
2552 if (indent)
2553     {
2554     fprintf(outfile,
2555             " firstindent %d leftindent %d",
2556             LEFTINDENT,
2557             LEFTINDENT);
2558     }
2559
2560 handle_link_and_graphic(m_parent(0),
2561                         gentity,
2562                         gposition,
2563                         ghyperlink,
2564                         glinktype,
2565                         gdescription);
2566
2567 fprintf(outfile, "%s>", listinfo);
2568
2569 unleaded = FALSE;
2570 }
2571
2572 #if defined(M_PROTO)
2573 void figure(
2574        M_WCHAR *number,
2575        M_WCHAR *tonumber,
2576        M_WCHAR *id,
2577        M_WCHAR *file,
2578        M_WCHAR *figpos,
2579        M_WCHAR *cappos,
2580        M_WCHAR *oldtype,
2581        M_WCHAR *xwidth,
2582        M_WCHAR *xdepth,
2583        M_WCHAR *xhadjust,
2584        M_WCHAR *xvadjust,
2585        M_WCHAR *border,
2586        M_WCHAR *type,
2587        M_WCHAR *xmagnify,
2588        M_WCHAR *video,
2589        M_WCHAR *strip,
2590        M_WCHAR *mirror,
2591        M_WCHAR *margin,
2592        M_WCHAR *clip,
2593        M_WCHAR *penwidth,
2594        M_WCHAR *snap,
2595        M_WCHAR *autoscale,
2596        M_WCHAR *plottype,
2597        M_WCHAR *callout,
2598        M_WCHAR *textsize,
2599        M_WCHAR *ghyperlink,
2600        M_WCHAR *glinktype,
2601        M_WCHAR *gdescription,
2602        char    *listinfo)
2603 #else
2604 void figure(
2605        number,
2606        tonumber,
2607        id,
2608        file,
2609        figpos,
2610        cappos,
2611        oldtype,
2612        xwidth,
2613        xdepth,
2614        xhadjust,
2615        xvadjust,
2616        border,
2617        type,
2618        xmagnify,
2619        video,
2620        strip,
2621        mirror,
2622        margin,
2623        clip,
2624        penwidth,
2625        snap,
2626        autoscale,
2627        plottype,
2628        callout,
2629        textsize,
2630        ghyperlink,
2631        glinktype,
2632        gdescription,
2633        listinfo)
2634 M_WCHAR *number;
2635 M_WCHAR *tonumber;
2636 M_WCHAR *id;
2637 M_WCHAR *file;
2638 M_WCHAR *figpos;
2639 M_WCHAR *cappos;
2640 M_WCHAR *oldtype;
2641 M_WCHAR *xwidth;
2642 M_WCHAR *xdepth;
2643 M_WCHAR *xhadjust;
2644 M_WCHAR *xvadjust;
2645 M_WCHAR *border;
2646 M_WCHAR *type;
2647 M_WCHAR *xmagnify;
2648 M_WCHAR *video;
2649 M_WCHAR *strip;
2650 M_WCHAR *mirror;
2651 M_WCHAR *margin;
2652 M_WCHAR *clip;
2653 M_WCHAR *penwidth;
2654 M_WCHAR *snap;
2655 M_WCHAR *autoscale;
2656 M_WCHAR *plottype;
2657 M_WCHAR *callout;
2658 M_WCHAR *textsize;
2659 M_WCHAR *ghyperlink;
2660 M_WCHAR *glinktype;
2661 M_WCHAR *gdescription;
2662 char    *listinfo;
2663 #endif
2664 {
2665 unsigned char etype,wheredef;
2666 char *string = 
2667     GetDefaultHeaderString("FigureElementDefaultHeadingString",
2668                            M_SDATA,
2669                            "Figure");
2670
2671 fprintf(outfile, "<PARAGRAPH%s>\n", listinfo);
2672 rshnewclear() ;
2673 figcaption = FALSE;
2674 ftonumber = (!tonumber || (vnumber(tonumber) == NUMBER));
2675 if (id && ! ftonumber)
2676     {
2677     m_error("Figures with ID's must be numbered");
2678     ftonumber = NUMBER;
2679     }
2680 if (ftonumber) figno++;
2681
2682 if (number)
2683     {
2684     char *mb_number;
2685
2686     mb_number = MakeMByteString(number);
2687     figno = atoi(mb_number);
2688     m_free(mb_number,"multi-byte string");
2689     if (! ftonumber)
2690     m_err1(
2691     "Explicit figure number %s inconsistent with NONUMBER option",
2692     number);
2693     }
2694 svheadlen = 0;
2695 *savehead = M_EOS;
2696 if (id)
2697     {
2698     char mb_xrefstring[400];
2699
2700     sprintf(mb_xrefstring, "%s %d", string, figno);
2701     mbstowcs(xrefstring, mb_xrefstring, 400);
2702     xstrlen = w_strlen(xrefstring);
2703     m_getline(&xrffile, &xrfline);
2704     if (xrffile == NULL)
2705         {
2706         /* set to primary input source */
2707         xrffile = inputname;
2708         }
2709     setid(id, TRUE, FALSE, inchapter, chapstring, xrffile, xrfline, TRUE);
2710     }
2711
2712 /* initialize some stuff first:
2713 - file is the entity name,
2714 - f_file is the content of the entity,
2715 used only if f_content nonNULL
2716 - f_content is f_file with the relative pathname, initialized to NULL,
2717 - f_contqual is fully qualified f_file, assigned ONLY IF
2718 f_content nonNULL
2719 */
2720 file_ent = FALSE;
2721 f_content = NULL;
2722 f_contqual[0] = M_EOS;
2723
2724 /* check ENTITY and determine the figure type  */
2725 if (file)
2726     {
2727     m_lookent(file, &etype, &f_file, &wheredef);
2728     if (etype != M_SYSTEM)
2729         {
2730         M_WCHAR *wc_stago, *wc_tagc;
2731         M_WCHAR *wc_entsystem, *wc_entkw;
2732
2733         wc_stago = MakeWideCharString(m_stago);
2734         wc_tagc  = MakeWideCharString(m_tagc);
2735         wc_entsystem  = MakeWideCharString(m_entsystem);
2736         wc_entkw  = MakeWideCharString(m_entkw);
2737         m_err6("%s not a %s %s, as required for the ENTITY parameter of %s%s%s",
2738                file,
2739                wc_entsystem,
2740                wc_entkw,
2741                wc_stago,
2742                m_parent(0),
2743                wc_tagc);
2744         m_free(wc_stago,"wide character string");
2745         m_free(wc_tagc,"wide character string");
2746         m_free(wc_entsystem,"wide character string");
2747         m_free(wc_entkw,"wide character string");
2748         }
2749     else
2750         {
2751         file_ent = TRUE;
2752         f_content = searchforfile(f_file);
2753         if (f_content)
2754             {
2755             if (getqualified(f_contqual, f_content))
2756                 {
2757                 /* unsuccessful qual */
2758                 if (w_strlen(f_content) < FNAMELEN)
2759                     w_strcpy(f_contqual, f_content);
2760                 else
2761                     {
2762                     m_err1("Internal error. File name too long: %s",
2763                            f_content);
2764                     m_exit(m_errexit);
2765                     }
2766                 }
2767             }
2768         else
2769             {
2770             m_err2("Can't find file %s (declared in entity %s)",
2771                    f_file,
2772                    file);
2773             }
2774         }
2775     }
2776
2777     {
2778     char *mb_content;
2779     static M_WCHAR empty = M_EOS;
2780
2781     if (!f_content) f_content = &empty;
2782
2783     mb_content = MakeMByteString(f_content);
2784     fprintf(outfile, "<FIGURE file %s", mb_content);
2785     m_free(mb_content,"multi-byte string");
2786     }
2787
2788 if (id)
2789     {
2790     char *mb_id;
2791
2792     mb_id = MakeMByteString(id);
2793     fprintf(outfile, " id %s", mb_id);
2794     m_free(mb_id,"multi-byte string");
2795     }
2796
2797 /* handle link specific code */
2798 if (!glinktype)
2799     { /* default to type jump */
2800     /* do nothing */
2801     }
2802 else
2803     { /* type is set, choose which is correct */
2804     if (!m_wcmbupstrcmp(glinktype, QJUMP))
2805         { fputs(" typelink 0", outfile); }
2806     else if (!m_wcmbupstrcmp(glinktype, QJUMPNEWVIEW))
2807         { fputs(" typelink 1", outfile); }
2808     else if (!m_wcmbupstrcmp(glinktype, QDEFINITION))
2809         { fputs(" typelink 2", outfile); }
2810     else if (!m_wcmbupstrcmp(glinktype, QEXECUTE))
2811         { fputs(" typelink 3", outfile); }
2812     else if (!m_wcmbupstrcmp(glinktype, QMAN))
2813         { fputs(" typelink 4", outfile); }
2814     else if (!m_wcmbupstrcmp(glinktype, QAPPDEFINED))
2815         { fputs(" typelink 5", outfile); }
2816     else /* parser won't let this case happen */
2817         {
2818         M_WCHAR *wc_stago, *wc_tagc;
2819
2820         wc_stago = MakeWideCharString(m_stago);
2821         wc_tagc  = MakeWideCharString(m_tagc);
2822         m_err3("%sLINK%s (glinktype=``%s'') did not match an allowed value",
2823                wc_stago,
2824                wc_tagc,
2825                glinktype); 
2826         m_free(wc_stago,"wide character string");
2827         m_free(wc_tagc,"wide character string");
2828         }
2829     }
2830 if (ghyperlink)
2831     {
2832     char *mb_ghyperlink;
2833
2834     mb_ghyperlink = MakeMByteString(ghyperlink);
2835     fprintf(outfile, " link \"%s\"", mb_ghyperlink);
2836     m_free(mb_ghyperlink,"multi-byte string");
2837     }
2838 else
2839     {
2840     if (glinktype || gdescription)
2841         {
2842         m_eprefix();
2843         fprintf(stderr,
2844                 "Error: %sP%s ghyperlink was undefined.\n",
2845                 m_stago,
2846                 m_tagc);
2847         fprintf(m_errfile,
2848                 "Error: %sP%s ghyperlink was undefined.\n",
2849                 m_stago,
2850                 m_tagc);
2851         fprintf(stderr,
2852     "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
2853                 QJUMP,
2854                 QJUMPNEWVIEW,
2855                 QDEFINITION,
2856                 QEXECUTE,
2857                 QAPPDEFINED,
2858                 QMAN);
2859         fprintf(m_errfile,
2860     "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
2861                 QJUMP,
2862                 QJUMPNEWVIEW,
2863                 QDEFINITION,
2864                 QEXECUTE,
2865                 QAPPDEFINED,
2866                 QMAN);
2867         m_errline("Use ``ghyperlink='' if the value contains non-alphabetics");
2868         m_esuffix();
2869         fputs(" glink _undefined", outfile);
2870         }
2871     }
2872
2873 if (gdescription)
2874     {
2875     char *mb_gdescription;
2876
2877     mb_gdescription = MakeMByteString(gdescription);
2878     fprintf(outfile, " description \"%s\"", mb_gdescription);
2879     m_free(mb_gdescription,"multi-byte string");
2880     }
2881 /* end of link specific code */
2882
2883 /* if caption position is not specified, have it track the figure position */
2884 if (!cappos)
2885     cappos = figpos;
2886
2887 if (figpos)
2888     switch (vcenter(figpos))
2889         {
2890         case LEFT:
2891             fputs(" left", outfile);
2892             break;
2893         case CENTER:
2894             fputs(" center", outfile);
2895             break;
2896         case RIGHT:
2897             fputs(" right", outfile);
2898             break;
2899         }
2900 if (cappos)
2901     switch (vcenter(cappos))
2902         {
2903         case LEFT:
2904             fputs(" cleft", outfile);
2905             break;
2906         case CENTER:
2907             fputs(" ccenter", outfile);
2908             break;
2909         case RIGHT:
2910             fputs(" cright", outfile);
2911             break;
2912         }
2913 fputs(" ctop>\n", outfile);
2914
2915 if (ftonumber)
2916     {
2917     fprintf(outfile, "%s %d.  ", string, figno);
2918     }
2919 m_free(string, "default header string return");
2920 }
2921
2922 #if defined(M_PROTO)
2923 void endterm( M_WCHAR *base, M_WCHAR *gloss, int linktype)
2924 #else
2925 void endterm( base, gloss, linktype)
2926 M_WCHAR *base;
2927 M_WCHAR *gloss;
2928 int     linktype;
2929 #endif
2930 {
2931 M_WCHAR *p;
2932 M_WCHAR wnl, wsp, wus;
2933
2934 tooutput = TRUE;
2935
2936 mbtowc(&wnl, "\n", 1);
2937 mbtowc(&wsp, " ", 1);
2938 mbtowc(&wus, "_", 1);
2939
2940 /* strip possible newlines out of base form */
2941 if (base)
2942     {
2943     for (p = base; *p ; p++)
2944         {
2945         if (*p == wnl) *p = wsp;
2946         }
2947     }
2948
2949 /* terminate the term string */
2950 if (termp - term > MAXTERM) termp = &term[MAXTERM];
2951 *termp = M_EOS;
2952
2953 /* trim possible last space */
2954 if (termp - term > 1 && *(termp-1) == wsp)
2955     {
2956     *(termp-1) = M_EOS;
2957     }
2958
2959 /* Check if it should be entered into the glossary structure */
2960 if (vgloss(gloss) == GLOSS)
2961     {
2962     m_ntrtrie(base ? base : term, &gtree, (M_TRIE *) ENTERTERM);
2963     fprintf(outfile, "<LINK %d \"", linktype);
2964     for (p = base ? base : term; *p; p++)
2965         {
2966         if (*p == wsp)
2967             {
2968             outchar(wus, outfile);
2969             }
2970         else
2971             {
2972             outchar(wc_toupper(*p), outfile);
2973             }
2974         }
2975     fputs("_DEF\">", outfile);
2976     }
2977
2978 /* Handle the output */
2979 mb_strcode("<WEIGHT bold>", outfile);
2980
2981 if (m_mblevel("EXAMPLESEG") || m_mblevel("IMAGE"))
2982     {
2983     /* Are we in one of these? */
2984     for(p = term; *p; p++)
2985         {
2986         exoutchar(*p);
2987         }
2988     }
2989 else
2990     { /* normal case */
2991     for(p = term; *p; p++)
2992         {
2993         outchar(*p, outfile);
2994         }
2995     }
2996
2997 mb_strcode("</WEIGHT>", outfile);
2998
2999 if (vgloss(gloss) == GLOSS)
3000     {
3001     mb_strcode("</LINK>", outfile);
3002     }
3003
3004 if (echo) mb_echohead("++");
3005 }
3006
3007 #if defined(M_PROTO)
3008 M_WCHAR wc_toupper(M_WCHAR wc)
3009 #else
3010 M_WCHAR wc_toupper(wc)
3011 M_WCHAR wc;
3012 #endif
3013 {
3014 if ((wc >= 0) && (wc <= 255))
3015     {
3016     return _toupper(wc);
3017     }
3018 return wc;
3019 }