2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
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 */
30 /* Start an appendix */
31 void appstart(id, letter)
34 M_WCHAR *p, *q, wnull;
48 /* Calculate the letter of the appendix in sequence */
52 itoletter(chapter, 'A', chapstring, sizeof(chapstring) - 1);
55 /* User-specified letter */
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
63 for (; *p >= '0' && *p <= '9' ; p++)
64 chapinc = 10 * chapinc + *p - '0';
65 if ((long) (int) xchapter != xchapter)
67 m_err1("%s: Too many characters in appendix letter", letter);
70 else chapter = (int) xchapter;
71 mbtowc(&wnull, "", 1);
72 for (pc = chapstring, q = letter; *q != wnull ; pc += length, q++)
74 char mbyte[32]; /* larger than the largest possible multibyte char */
75 length = wctomb(mbyte, *q);
76 if ((pc + length) >= (&chapstring[sizeof(chapstring) - 1]))
78 m_err1("%s: Too many characters in appendix letter", letter);
86 fprintf(stderr, "\nAppendix %s. ", chapstring);
98 void assert_hometopic_exists(M_NOPAR)
101 GetDefaultHeaderString("UntitledElementDefaultHeadingString",
108 mb_starthelpnode("_HOMETOPIC", FALSE);
112 pc = MakeMByteString(savedtitle);
115 "<TITLE><TYPE serif><WEIGHT bold><SIZE 14>",
117 "</SIZE></WEIGHT></TYPE></TITLE>\n");
119 m_free(pc, "multi-byte string");
121 m_free(string, "GetDefaultHeaderString return");
124 /* Determine base name for files (i.e., input name without extension).
125 Open output and error files */
126 void basename(M_NOPAR)
134 m_error("Specify input file");
138 (strchr(m_argv[2], 'f') || strchr(m_argv[2], 'F'))
141 /* Get installation directory */
143 for (p = m_argv[0]; *p ; p++);
145 if (*p == dirsep || *p == ':') break;
149 install = m_malloc(strlen(m_argv[0]) + 1, "installation directory");
150 strcpy(install, m_argv[0]);
154 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
155 #define CONTRIB "/usr/hphelp/bin/"
157 /* get our path if we can */
158 /* A hacked up ``which'', just to find our directory */
159 /* fills ``install'' with path to ourself */
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 */
177 if (p < m_argv[0]) m_error("Internal Error.");
178 if (*p == dirsep) break;
180 p++; /* just past the dirsep */
183 install = (char *)m_malloc(strlen(m_argv[0]) + 1, "installation directory");
184 strcpy(install, m_argv[0]);
187 none = 0; /* we've got it. */
190 m_error("Internal Error (which).");
194 /* not fully specified, check each component of path for ourself */
195 strcpy(patbuf, getenv("PATH"));
200 cp = strchr(path, ':');
205 sprintf(buf, "%s/%s", path, m_argv[0]);
207 if (access(buf, 1) == 0) {
208 install = (char*) m_malloc(strlen(path) + 1,
209 "installation directory");
210 strcpy(install, path);
213 /* else, not an error if we can't find a particular one. */
217 break; /* either out of paths, or we found it. */
223 /* can't get it, use default */
224 install = (char*) m_malloc(strlen(CONTRIB) + 1,
225 "installation directory");
226 strcpy(install, CONTRIB);
228 /* else -- we've got it */
232 Get installation directory
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
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]);
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;
262 m_malloc(strlen(p) + 1, "basename without directory");
263 strcpy(nodirbase, p);
264 /* Get working directory option, if specified */
266 base = (char *) m_malloc(n + strlen(".htg") + 1, "basename");
269 baseext = base + n + 1;
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);
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);
290 /* Open error files */
292 m_openchk(&m_errfile, "filelist.err", "w");
295 strcpy(helpext, ".err");
296 m_openchk(&m_errfile, helpbase, "w");
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 */
313 char *chapterPrefixString =
314 GetDefaultHeaderString("ChapterElementDefaultHeadingString",
317 char *chapterSuffixString =
318 GetDefaultHeaderString("ChapterSuffixElementDefaultHeadingString",
321 char *partPrefixString =
322 GetDefaultHeaderString("PartElementDefaultHeadingString",
325 char *partSuffixString =
326 GetDefaultHeaderString("PartSuffixElementDefaultHeadingString",
330 rsectseq = FALSE; /* CHAPTERs only; irrelevant for PART */
331 chapst = FALSE; /* CHAPTERs only; irrelevant for PART */
337 chapter++; /* CHAPTER processing */
338 m_itoa(chapter, chapstring);
343 m_itoa(part, chapstring);
348 mbyte = MakeMByteString(number);
349 chapter = atoi(mbyte);
350 m_free(mbyte,"multi-byte string");
352 for (p = number; *p >= '0' && *p <= '9' ; p++);
353 for (; *p >= 'A' && *p <= 'Z' ; p++)
354 chapinc = 26 * chapinc + *p + 1 - 'A';
356 mbyte = MakeMByteString(number);
357 if (strlen(mbyte) + 1 > sizeof(chapstring))
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);
365 strcpy(chapstring, mbyte);
366 m_free(mbyte,"multi-byte string");
371 if ((length = mblen(pc,32)) == 1)
372 *pc = isupper(*pc) ? tolower(*pc) : *pc;
377 { /* chapter, not part */
388 *type=='c' ? chapterPrefixString : partPrefixString,
390 *type=='c' ? chapterSuffixString : partSuffixString
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");
400 /*****************************************************************
401 *****************************************************************
402 CDROM routines: check to see if sdata is supported in cdrom
404 #define STATIC static
406 * define arrays specifing laserrom defined entities.
407 * these are used to override "texchar.ent" SDATA && PI definitions.
418 * the last entry in this array should always be
431 {"MINUS", "\\symbol{4}"},
433 {"DIV", "\\symbol{5}"},
434 {"TIMES", "\\times "},
435 {"LEQ", "\\symbol{12}"},
436 {"GEQ", "\\symbol{13}"},
437 {"NEQ", "\\symbol{14}"},
440 {"TM", "\\special{{PLU}}TM\\special{{PLD}}"},
441 {"ELLIPSIS", "\\symbol{18}"},
442 {"VELLIPSIS", "\\symbol{7}"},
444 {"SQUOTE", "\\symbol{8}"},
445 {"DQUOTE", "\\symbol{9}"},
446 {"ENDASH", "\\symbol{10}"},
447 {"EMDASH", "\\symbol{21}"},
450 {"STERLING", "sterling"},
451 {"PELLIPSIS", "...."},
454 {"HALFSPACE", "\\ "},
455 {"MICRO", "\\symbol{24}"},
458 {"DOWN", "down arrow"},
459 {"LEFT", "left arrow"},
460 {"RIGHT", "right arrow"},
461 {"HOME", "home arrow"},
462 {"BACK", "[[backspace]]"},
467 {"MINUTES", "\\squote "},
468 {"SECONDS", "\\dquote "},
474 {"epsilon", "epsilon"},
475 {"varepsilon", "varepsilon"},
479 {"vartheta", "vartheta"},
482 {"lambda", "lambda"},
489 {"varrho", "varrho"},
491 {"varsigma", "varsigma"},
493 {"upsilon", "upsilon"},
495 {"varphi", "varphi"},
502 {"ULambda", "Lambda"},
506 {"UUpsilon", "Upsilon"},
538 {"imath", "\\it{i}"},
539 {"jmath", "\\it{j}"},
545 {"infty", "infinity"},
548 {"prime", "\\symbol{8}"},
549 {"emptyset", "empty set"},
556 {"triangle", "triangle"},
557 {"backslash", "\\\\"},
559 {"forall", "forall"},
560 {"exists", "exists"},
563 {"natural", "natural"},
565 {"clubsuit", "clubs"},
566 {"diamondsuit", "diamonds"},
567 {"heartsuit", "hearts"},
568 {"spadesuit", "spades"},
571 {"coprod", "coprod"},
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"},
584 {"setminus", "\\\\"},
585 {"cdot", "\\special{{PLU}}.\\special{{PLD}}"},
588 {"diamond", "diamond"},
590 {"bullet", "bullet"},
596 {"triangleleft", "triangleleft"},
597 {"triangleright", "triangleright"},
599 {"bigcirc", "bigcirc"},
600 {"bigtriangleup", "triangleup"},
601 {"bigtriangledown", "triangledown"},
605 {"ominus", "ominus"},
606 {"otimes", "otimes"},
607 {"oslash", "oslash"},
613 {"preceq", "preceq"},
615 {"subset", "subset"},
616 {"subseteq", "subseteq"},
617 {"sqsubseteq", "sqsubseteq"},
623 {"succeq", "succeq"},
625 {"supset", "supset"},
626 {"supseteq", "supseteq"},
627 {"sqsupseteq", "sqsupseteq"},
636 {"approx", "approx"},
638 {"bowtie", "bowtie"},
639 {"propto", "propto"},
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"},
651 {"not-sim", "not sim"},
652 {"not-approx", "not approx"},
653 {"not-asymp", "not asymp"},
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"},
665 {"bigleftarrow", "<="},
666 {"rightarrow", "->"},
667 {"bigrightarrow", "=>"},
668 {"leftrightarrow", "<->"},
669 {"bigleftrightarrow", "<=>"},
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"},
698 {"threequarter", "3/4"},
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"},
716 * the last entry in this array should always be
723 /* Verify Tag dimension, else issue error message */
724 M_WCHAR *checkdimen( val, paramname, elt )
729 /* returns val if a valid TeX dimension, else NULL */
730 M_WCHAR *valid = NULL;
732 if ( val == NULL ) return ( NULL );
733 if ((valid = okdimen(val)) != NULL) return(valid);
736 M_WCHAR *wc_stago, *wc_tagc;
738 wc_stago = MakeWideCharString(m_stago);
739 wc_tagc = MakeWideCharString(m_tagc);
740 m_err5 ("[%s] Illegal value of %s for %s%s%s",
746 m_free(wc_stago,"wide character string");
747 m_free(wc_tagc,"wide character string");
753 M_WCHAR *mb_checkdimen( val, paramname, elt )
758 M_WCHAR *wc_paramname, *wc_elt, *retval;
760 wc_paramname = MakeWideCharString(paramname);
761 wc_elt = MakeWideCharString(elt);
763 retval = checkdimen(val, wc_paramname, wc_elt);
765 m_free(wc_paramname,"wide character string");
766 m_free(wc_elt,"wide character string");
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)
776 char *mb_entc, mb_filen[2048];
777 int dir_leng, econt_leng;
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");
789 econt_leng = strlen(mb_entc);
790 for (searchp = path; searchp ; searchp = searchp->next)
792 if (((dir_leng = strlen(searchp->directory)) + econt_leng) >= 2048)
796 wc = MakeWideCharString(searchp->directory);
797 m_err2("%s and %s overflow the file name space",
800 m_free(wc,"wide character string");
803 strcpy(mb_filen, searchp->directory);
804 strcpy(mb_filen + dir_leng, mb_entc);
805 if (access(mb_filen, 04)==0) /* entcontent is readable */
807 m_free(mb_entc,"multi-byte string");
808 return MakeWideCharString(mb_filen);
812 m_free(mb_entc,"multi-byte string");
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)
822 M_WCHAR id[MAXTERM + 1];
823 M_TRIE *node[MAXTERM + 1];
826 if (! gtree.data) return;
828 current = gtree.data;
831 id[n] = current->symbol;
832 node[n] = current->next;
835 if ((unsigned) current->data != DEFINETERM)
836 m_err1("No glossary definition for %s", id);
837 current = current->next;
847 current = current->data;
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)
859 GetDefaultHeaderString("MessagesElementDefaultHeadingString",
862 if (emsghead == DEFHEAD)
863 { /* head not output yet */
866 "<TITLE><TYPE serif><WEIGHT bold><SIZE 14>",
868 "</TYPE></WEIGHT></SIZE></TITLE>\n");
871 else if (emsghead == USERHEAD)
872 { /* user specified head */
875 m_free(string, "GetDefaultHeaderString return");
876 } /* end checkmsghead() */
879 /* Verify that val is an acceptable real number value */
882 checkreal (M_WCHAR *val, M_WCHAR *paramname, LOGICAL msgout, M_WCHAR *elt)
884 M_WCHAR *checkreal (val, paramname, msgout, elt)
885 M_WCHAR *val, *paramname;
890 /* returns val if a valid real number, else NULL */
892 M_WCHAR *valid = NULL;
893 char s1[M_NAMELEN+1];
896 if (val == NULL) return NULL;
898 mbyte = MakeMByteString(val);
900 if (sscanf (mbyte, "%lf", &num ) == 1 ) valid = val;
902 if (sscanf(mbyte, "%lf%s", &num, s1 ) == 2 )
903 valid = NULL; /* no characters allowed */
907 M_WCHAR *wc_stago, *wc_tagc;
911 wc_stago = MakeWideCharString(m_stago);
912 wc_tagc = MakeWideCharString(m_tagc);
913 m_err5("[%s] Illegal value of %s for %s%s%s",
919 m_free(wc_stago,"wide character string");
920 m_free(wc_tagc,"wide character string");
924 m_free(mbyte,"multi-byte string");
926 } /* END checkreal procedure */
929 /* end a help node */
930 void endhelpnode(M_NOPAR)
934 /* End code for <EX> and <VEX> */
935 void exvexend (textsize)
940 tsize = vextextsize(textsize);
943 fputs("</SPACING></TYPE></PARAGRAPH>\n\n", outfile);
946 { /* textsize is either SMALLER or SMALLEST */
947 fputs("</SIZE>\n</SPACING></TYPE></PARAGRAPH>\n\n", outfile);
949 } /* END exvexend() */
952 /* Starting stuff for <EX> and <VEX> */
954 void exvexstart (M_WCHAR *type, M_WCHAR *textsize, char *listinfo)
956 void exvexstart (type, textsize, listinfo)
957 M_WCHAR *type, *textsize;
966 tsize = vextextsize(textsize);
970 "<PARAGRAPH%s firstindent %d leftindent %d nowrap><TYPE serif><SPACING m>",
976 { /* textsize is either SMALLER or SMALLEST */
978 "<PARAGRAPH%s firstindent %d leftindent %d nowrap><TYPE serif><SPACING m>",
984 fputs("<SIZE 8>", outfile);
988 fputs("<SIZE 6>", outfile);
991 } /* END exvexstart() */
994 /* construct a qualified file name */
995 int mb_getqualified ( qualname, unqualname )
999 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
1003 char tokstr [ 20 ], *gp, *p, *pp, *fnp, curdir[FNAMELEN-1];
1004 int roomleft = FNAMELEN - 1;
1012 if (strlen(unqualname) < FNAMELEN)
1013 strcpy(fn, unqualname );
1016 m_mberr1("Internal Error. File name too long for qualifying: %s",
1023 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
1025 gp = qualname + strlen(qualname);
1026 roomleft = roomleft - strlen(qualname);
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 */
1033 strcat(qualname, SSEP);
1039 f = popen("/bin/pwd", "r");
1040 fscanf(f, "%s", gp);
1042 if (strlen(gp) >= roomleft)
1044 m_mberr1("Internal error: possible stray pointer in getqualified(): %s",
1048 strcat(qualname,SSEP);
1052 /* if MS-DOS, force to upper case, then get drive spec */
1054 if ( fn[1] == ':' ) {
1055 strncpy ( qualname, fn, 2 );
1059 getcwd(qualname, roomleft);
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 );
1072 /* assume current directory always !!! */
1074 getcwd(curdir, FNAMELEN-1);
1075 if (*curdir != *qualname) {
1076 m_err1("Relative directory %s for non-current drive, can't qualify",
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 */
1087 m_err1("Internal error. File name too long for qualifying: %s",
1095 strcpy(tokstr, " \r\n\t");
1096 strcat(tokstr, SSEP);
1099 p = strtok(( p == NULL ) ? fnp : NULL, tokstr);
1100 if ( p == NULL ) break;
1101 if ( *p == '.' ) /* alias */
1103 if ( *(p+1) == '.' ) /* parent */
1105 *strrchr(qualname, CSEP) = '\0';
1106 pp = strrchr(qualname, CSEP);
1107 if (pp == NULL) /* FAIL */
1109 m_mberr1("Internal error. Failed in qualifying %s", unqualname);
1120 if ((strlen(p)+1) < roomleft)
1121 { /* "1" for SSEP */
1122 strcat(qualname, p);
1123 strcat(qualname, SSEP);
1124 roomleft = roomleft - strlen(p) - 1;
1128 m_mberr1("Internal error. File name too long for qualifying: %s",
1135 *strrchr(qualname, CSEP) = '\0';
1137 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
1139 strupr ( qualname );
1143 } /* end mb_getqualified */
1146 int getqualified (qualname, unqualname)
1148 M_WCHAR *unqualname;
1151 char mb_qualname[FNAMELEN],
1152 mb_unqualname[FNAMELEN];
1154 wcstombs(mb_qualname, qualname, FNAMELEN);
1155 wcstombs(mb_unqualname, unqualname, FNAMELEN);
1157 retval = mb_getqualified(mb_qualname, mb_unqualname);
1159 mbstowcs(qualname, mb_qualname, FNAMELEN);
1160 mbstowcs(unqualname, mb_unqualname, FNAMELEN);
1166 /* handle the common link and graphic code for <p> and <image> */
1168 handle_link_and_graphic(parent,
1174 M_WCHAR *parent, *gentity, *gposition, *ghyperlink, *glinktype, *gdescription;
1176 unsigned char etype, wheredef;
1178 static M_WCHAR empty = M_EOS;
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
1190 f_contqual[0] = M_EOS;
1192 /* check ENTITY and determine the figure type */
1195 m_lookent(gentity, &etype, &f_file, &wheredef);
1196 if (etype != M_SYSTEM)
1198 M_WCHAR *wc_entsystem, *wc_entkw, *wc_stago, *wc_tagc;
1200 wc_entsystem = MakeWideCharString(m_entsystem);
1201 wc_entkw = MakeWideCharString(m_entkw);
1202 wc_stago = MakeWideCharString(m_stago);
1203 wc_tagc = MakeWideCharString(m_tagc);
1205 "%s not a %s %s, as required for the ENTITY parameter of %s%s%s",
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");
1220 f_content = searchforfile(f_file);
1223 if (getqualified(f_contqual, f_content))
1225 /* unsuccessful qual */
1226 if (w_strlen(f_content) < FNAMELEN)
1227 w_strcpy(f_contqual, f_content);
1230 m_err1("Internal error. File name too long: %s",
1238 m_err2("Can't find file %s (declared in entity %s)",
1243 if (!f_content) f_content = ∅
1245 mb_content = MakeMByteString(f_content);
1246 fprintf(outfile, " graphic %s", mb_content);
1247 m_free(mb_content,"multi-byte string");
1250 /* and the position now */
1253 M_WCHAR *wc_left, *wc_right;
1255 wc_left = MakeWideCharString(QLEFT);
1256 if (!m_wcupstrcmp(gposition, wc_left))
1258 fputs(" gpos left", outfile);
1262 wc_right = MakeWideCharString(QRIGHT);
1263 if (!m_wcupstrcmp(gposition, wc_right))
1265 fputs(" gpos right", outfile);
1269 m_err1("Invalid value for gposition: `%s'", gposition);
1271 m_free(wc_right,"wide character string");
1273 m_free(wc_left,"wide character string");
1276 /* end handling graphic specific code */
1277 /* handle link specific code */
1279 { /* default to type jump */
1283 { /* type is set, choose which is correct */
1284 M_WCHAR *wc_stago, *wc_tagc;
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); }
1299 { /* parser won't let this case happen */
1300 wc_stago = MakeWideCharString(m_stago);
1301 wc_tagc = MakeWideCharString(m_tagc);
1303 "%sLINK%s (glinktype=``%s'') did not match an allowed value",
1307 m_free(wc_stago,"wide character string");
1308 m_free(wc_tagc,"wide character string");
1314 char *mb_ghyperlink;
1316 mb_ghyperlink = MakeMByteString(ghyperlink);
1317 fprintf(outfile, " glink \"%s\"", mb_ghyperlink);
1318 m_free(mb_ghyperlink,"multi-byte string");
1322 if (glinktype || gdescription)
1326 "Error: %sP%s ghyperlink was undefined.\n",
1330 "Error: %sP%s ghyperlink was undefined.\n",
1334 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
1342 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
1349 m_errline("Use ``ghyperlink='' if the value contains non-alphabetics");
1351 fputs(" glink _undefined", outfile);
1357 fprintf(outfile, " description \"%s\"", gdescription);
1359 /* end of link specific code */
1362 /* Process an item in a list */
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;
1384 if (lastlist->lastlist->type == ORDER)
1385 fprintf(outfile, "<PARAGRAPH leftindent %d", ORDEREDLISTITEMINDENT);
1387 fprintf(outfile, "<PARAGRAPH leftindent %d", LISTITEMINDENT);
1389 if (lastlist->lastlist->space == TIGHT)
1391 fputs(" after 0", outfile);
1393 lastlist->lastlist->where = FIRST;
1395 orderString[0] = '\0';
1396 count = ++lastlist->lastlist->count;
1397 if (count > 999) count = 999; /* holy cow! Big list. */
1398 switch (lastlist->lastlist->order)
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)
1408 tmpString[0] = '\0';
1410 while (--count >= 0) strcat(tmpString, "\\ ");
1411 strcat(tmpString, orderString);
1412 strcpy(orderString, tmpString);
1417 while ((count -= 26) > 0) metaCount++;
1418 count = lastlist->lastlist->count;
1419 if (count > 999) count = 999;
1422 while (--metaCount >= 0) strncat(orderString, &ALPHABET[count], 1);
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);
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)
1439 tmpString[0] = '\0';
1441 while (--count >= 0) strcat(tmpString, "\\ ");
1442 strcat(tmpString, orderString);
1443 strcpy(orderString, tmpString);
1448 while ((count -= 26) > 0) metaCount++;
1449 count = lastlist->lastlist->count;
1450 if (count > 999) count = 999;
1453 while (--metaCount >= 0) strncat(orderString, &alphabet[count], 1);
1457 if (lastlist->lastlist->type == ORDER)
1459 fprintf( /* keep the '('s balanced */
1461 "><LABEL><WEIGHT bold>%s%2s%c</WEIGHT></LABEL",
1462 (strlen(orderString) > 1) ? "" : "\\",
1464 lastlist->lastlist->punct == DOTPUNCT ? '.' : ')' );
1467 char buffer[400], *mbyte;
1470 sprintf(buffer, "Item %s", orderString);
1471 wc = MakeWideCharString(buffer);
1472 w_strcpy(xrefstring, wc);
1473 m_free(wc,"wide character string");
1475 xstrlen = w_strlen(xrefstring);
1476 m_getline(&xrffile, &xrfline);
1477 if (xrffile == NULL)
1479 /* set to primary input */
1480 xrffile = inputname;
1491 mbyte = MakeMByteString(id);
1492 fprintf(outfile, " id \"%s\"", id);
1493 m_free(mbyte,"multi-byte string");
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)
1502 "><LABEL><CHARACTERSET symbol>%c</></LABEL",
1503 183 /* BULLET CHAR */ );
1505 else if (lastlist->lastlist->type == CHECK)
1507 /* no hollow square in the symbol charset, use hollow diamond */
1509 "><LABEL><CHARACTERSET symbol>%c</></LABEL",
1510 224 /* CHECK CHAR */ );
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");
1518 fputs(">\n", outfile);
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)
1526 void itoletter(n, start, dest, length)
1538 m_error("Internal error: converting non-positive number to letter");
1543 for (p = invert; n ; p++, n = (n - 1) / 26)
1545 *p = start + (n - 1) % 26;
1546 if (p == &invert[length] || p == &invert[sizeof(invert)])
1548 m_error("Internal error: out of space converting number to letter");
1557 if (p == invert) break;
1563 /* Start the <MANUAL> tag processing */
1564 void manustart(language, idxvol, status)
1565 M_WCHAR *language, *idxvol, *status;
1567 if (idxvol) w_strcpy(volume, idxvol);
1568 } /* END manustart procedure */
1571 /* Issue error message and text in document element is not supported in
1572 a particular option or context */
1573 void notimp(eltname, option)
1578 M_WCHAR *wc_stago, *wc_eltname, *wc_tagc, *wc_option;
1580 fputs("<PARAGRAPH><WEIGHT bold>", outfile);
1581 for (p = m_stago; *p ; p++)
1583 outchar(*p, outfile);
1585 fputs(eltname, outfile);
1586 for (p = m_tagc; *p ; p++)
1588 outchar(*p, outfile);
1590 fprintf(outfile, " not supported in %s.</WEIGHT></PARAGRAPH>\n\n", option);
1592 wc_stago = MakeWideCharString(m_stago);
1593 wc_eltname = MakeWideCharString(eltname);
1594 wc_tagc = MakeWideCharString(m_tagc);
1595 wc_option = MakeWideCharString(option);
1597 m_err4("%s%s%s not suppported in %s",
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");
1611 /* Close current output, construct new output name and open output */
1612 void open_new_helpfile()
1615 char htfilenostring[15];
1616 M_WCHAR *wc_1, *wc_2;
1620 fputs("</TOPIC>\n", outfile);
1624 m_itoa(htfileno++, htfilenostring);
1626 if ((j = strlen(htfilenostring)) > PRE_EXTENSION_LIMIT)
1628 helptmpbuf[0] = '0' + PRE_EXTENSION_LIMIT;
1629 helptmpbuf[1] = '\0';
1630 wc_1 = MakeWideCharString(htfilenostring);
1631 wc_2 = MakeWideCharString(helptmpbuf);
1633 "Error: Tail of new output help file, `%s', is longer than %s characters",
1636 m_free(wc_1,"wide character string");
1637 m_free(wc_2,"wide character string");
1643 case 0: m_error("Fatal Error: Null tail on new help file.");
1648 *(helpext + 1) = *htfilenostring;
1649 *(helpext + 2) = '\0';
1652 *helpext = htfilenostring[0];
1653 *(helpext + 1) = htfilenostring[1];
1654 *(helpext + 2) = '\0';
1657 m_error("Internal error. (helpext)");
1661 strcat(helpext, ".ht");
1662 m_openchk(&m_outfile, helpbase, "w");
1663 outfile = m_outfile;
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);
1672 } /* end procedure open_new_helpfile */
1675 /* Verify that val will be understandable to TeX as a dimension */
1676 M_WCHAR *okdimen ( val )
1679 /* returns val if a valid TeX dimension, else NULL */
1680 char s1[M_NAMELEN + 1], s2[M_NAMELEN + 1];
1683 M_WCHAR *valid = NULL;
1686 if ( val == NULL ) return ( NULL );
1688 mbyte = MakeMByteString(val);
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))
1697 m_free(mbyte,"multi-byte string");
1699 } /* END procedure okdimen */
1703 void rsectstart(id, pagebreak)
1704 M_WCHAR *id, *pagebreak;
1706 savid = checkid(id);
1710 M_WCHAR *wc_samepage;
1712 wc_samepage = MakeWideCharString(QSAMEPAGE);
1714 (rsectsame != (LOGICAL) (! m_wcupstrcmp(pagebreak,wc_samepage))))
1717 "%s specification ignored within a sequence of reference sections",
1720 m_free(wc_samepage,"wide character string");
1723 rsectholdnew = FALSE;
1728 rsectsame = (LOGICAL) (vrsectpage(pagebreak) == SAMEPAGE);
1730 rsectholdnew = FALSE;
1733 if (rsectsame && m_mblevel("S3")) st4 = TRUE;
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")) {}
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 */
1751 else /* rsect SAMEPAGE is first element in chapter, suppress rule */
1754 } /* END procedure rsectstart */
1757 /* Called at the end of a chapter, appendix, or section to end an open
1758 sequence of rsects */
1759 void rseqend(M_NOPAR)
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
1772 void rshnewclear(M_NOPAR)
1776 rsectholdnew = FALSE;
1780 /* Follow search path to find a file, returning qualified name */
1781 M_WCHAR *searchforfile(file)
1786 char *mb_file, mb_filename[2048];
1787 int dir_leng,file_leng;
1789 mb_file = MakeMByteString(file);
1790 if (! access(mb_file, READABLE))
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");
1799 file_leng = strlen(mb_file);
1800 for (searchp = path; searchp ; searchp = searchp->next)
1802 if (((dir_leng = strlen(searchp->directory)) + file_leng) >= 2048)
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");
1811 strcpy(mb_filename, searchp->directory);
1812 strcpy(mb_filename+dir_leng, mb_file);
1813 if (! access(mb_filename, READABLE))
1815 m_free(mb_file,"multi-byte string");
1816 return(MakeWideCharString(mb_filename));
1820 m_free(mb_file,"multi-byte string");
1825 /* show how much memory is available */
1826 void showmemavail(M_NOPAR)
1831 while (p = (char *) malloc(1024))
1834 if ( amount >= 512 ) break;
1839 /* Start a new helpnode */
1840 #if defined(M_PROTO)
1841 void starthelpnode(M_WCHAR *id, LOGICAL suppress_topic_map)
1843 void starthelpnode(id, suppress_topic_map)
1845 LOGICAL suppress_topic_map; /* should we suppress .tpc entry */
1850 char mb_nodeid[NODEID_LENGTH+1], nodenum[32];
1854 /* don't end nonexistent previous node */
1859 fprintf(outfile, "</TOPIC>\n\n");
1862 if (outfile != m_outfile)
1864 m_error("Internal warning: Outfile has been redirected.");
1869 nodeoffset = ftell(m_outfile);
1871 mbyte = MakeMByteString(helpcharset);
1872 fprintf(outfile, "<TOPIC charset %s>\n", mbyte);
1873 m_free(mbyte,"multi-byte string");
1875 if (nodeoffset == -1L)
1877 m_error("Internal error, node offset.");
1883 strcpy(mb_nodeid, "_TOPIC_ID_");
1884 m_itoa(autonodenumber, nodenum);
1885 strcpy(nodestring, nodenum);
1887 strcat(mb_nodeid, nodenum);
1888 mbstowcs(nodeid, mb_nodeid, NODEID_LENGTH);
1892 w_strncpy(nodeid, id, NODEID_LENGTH);
1893 wcstombs(mb_nodeid, id, NODEID_LENGTH);
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");
1901 if (!suppress_topic_map)
1903 /* handle TOPIC MAP file */
1905 if (thisnodelevel == lastnodelevel)
1906 { /* this node at same level */
1907 if (!isfirsttopicmap)
1909 fputs("\n", topicmapfp);
1913 isfirsttopicmap = FALSE;
1915 /* indent routine >here< */
1916 for (i = thisnodelevel; --i >= 0;) { fputs(" ", topicmapfp); }
1917 fprintf(topicmapfp, "%s", mb_nodeid);
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);
1928 if (thisnodelevel < lastnodelevel)
1929 { /* this node is higher */
1930 fputs("\n", topicmapfp);
1931 while (thisnodelevel != lastnodelevel--)
1933 /* indent routine >here< */
1934 for (i = lastnodelevel; --i >= 0;) { fputs(" ", topicmapfp); }
1935 /* keep the '{' balanced */
1936 fputs("}\n", topicmapfp);
1938 for (i = thisnodelevel; --i >= 0;) { fputs(" ", topicmapfp); }
1939 fprintf(topicmapfp, "%s", mb_nodeid);
1941 /* get ready for next time */
1942 lastnodelevel = thisnodelevel;
1944 } /* End starthelpnode(id) */
1947 #if defined(M_PROTO)
1948 void mb_starthelpnode(char *id, LOGICAL suppress_topic_map)
1950 void mb_starthelpnode(id, suppress_topic_map)
1952 LOGICAL suppress_topic_map; /* should we suppress .tpc entry */
1957 wc = MakeWideCharString(id);
1958 starthelpnode(wc, suppress_topic_map);
1959 m_free(wc,"wide character string");
1963 /* Start a labeled list */
1964 void startlablist(longlabel, width, spacing)
1965 M_WCHAR *longlabel, *width, *spacing;
1970 if (list > MAXLISTLEV)
1971 m_error("Nesting of <LIST> and <LABLIST> too deep");
1972 fputs("<PARAGRAPH>\n", outfile);
1973 if (list <= MAXLISTLEV)
1975 if (vspacing(spacing) == TIGHT)
1977 lablistindented[list] = TRUE;
1981 lablistindented[list] = FALSE;
1987 void startlist(type, order, spacing, cont)
1988 M_WCHAR *type, *order, *spacing, *cont;
1999 /* Set ``paragraph'' for a new list */
2000 if (type && !m_wcmbupstrcmp(type, QORDER))
2002 "<PARAGRAPH firstindent %d leftindent %d>\n",
2003 ORDEREDLISTFIRSTINDENT,
2004 ORDEREDLISTFIRSTINDENT);
2007 "<PARAGRAPH firstindent %d leftindent %d>\n",
2011 if (list > MAXLISTLEV)
2012 m_error("Nesting of <LIST> and <LABLIST> too deep");
2014 if (! lastlist->started && cont)
2016 m_error("No previous list to continue");
2022 if (order && (vordertype(order) != lastlist->order))
2024 m_error("Unable to continue a list and change the numbering scheme");
2028 if (type && (vtype(type) != lastlist->type))
2030 m_error("Unable to continue a list and change its type");
2036 { /* clear old list? */
2037 for (chain = lastlist->chain; chain ; chain = xchain)
2039 xchain = chain->next;
2040 m_free(chain, "list chain");
2042 lastlist->chain = NULL;
2043 lastlist->count = 0;
2046 /* If outermost list, initialize according to current defaults */
2047 if (! cont && lastlist == &outlist)
2049 outlist.type = vtype(NULL);
2050 outlist.order = vordertype(NULL);
2052 outlist.space = vspacing(NULL);
2053 outlist.punct = DOTPUNCT;
2056 if (type) lastlist->type = vtype(type);
2060 lastlist->type = ORDER;
2061 lastlist->order = vordertype(order);
2064 if (spacing && ! m_wcmbupstrcmp(spacing, QTIGHT)) lastlist->space = TIGHT;
2066 if (type && order && m_wcmbupstrcmp(type, QORDER))
2067 m_err2("Incompatible specification for list: %s and %s", type, order);
2069 if (lastlist->type == ORDER)
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);
2082 if (lastlist->type == PLAIN) {}
2083 else if (lastlist->type == BULLET) {}
2084 else if (lastlist->type == CHECK) {}
2085 lastlist->started = TRUE;
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)
2094 nextlist->order = lastlist->order + 1;
2095 if (nextlist->order > LROMAN)
2097 nextlist->order = ARABIC;
2098 nextlist->punct = PARENPUNCT;
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;
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)
2119 for (p = m_mdo; *p ; p++)
2125 for (p = m_comment; *p ; p++)
2131 for (p = "Index"; *p ; p++)
2137 m_entdupchk = FALSE;
2140 /* Open and initialize TeX file */
2141 void texinit(M_NOPAR)
2143 LOGICAL init = TRUE;
2146 unsigned char wheredef;
2154 M_WCHAR wbs, wsl, wcl;
2157 /* Check .XRF file */
2158 strcpy(helpext, ".xrh");
2159 xrf = fopen(helpbase, "r");
2160 if (! xrf) rebuild = TRUE;
2163 fscanf(xrf, "\\gobble\001");
2164 for (p = m_signon; *p ; p++)
2170 "Output files from different version of Tag, regenerating. . .\n");
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;
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;
2194 savehelpfilename = (M_WCHAR *)m_malloc(strlen(helpbase)+1, "help file name");
2195 mbstowcs(savehelpfilename, helpbase, strlen(helpbase) + 1);
2199 strcpy(helpext, ".hmi");
2200 m_openchk(&docregfp, helpbase, "w");
2204 strcpy(helpext, ".idt");
2205 m_openchk(&idtablefp, helpbase, "wb");
2207 /* topic map file */
2208 strcpy(helpext, ".tpc");
2209 m_openchk(&topicmapfp, helpbase, "wb");
2212 strcpy(helpext, ".idx");
2213 m_openchk(&indexfp, helpbase, "wb");
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);
2220 while (name = m_cyclent(init, &type, &content, &wheredef))
2226 if (type == M_SYSTEM)
2227 qfile = searchforfile(content);
2229 if (qfile) m_free(qfile, "figure filename");
2231 if (type == M_SYSTEM)
2233 mbtowc(&wbs, "\\", 1);
2234 mbtowc(&wsl, "/", 1);
2235 mbtowc(&wcl, ":", 1);
2237 if (w_strchr(content, wbs) ||
2238 w_strchr(content, wsl) ||
2239 w_strchr(content, wcl) )
2241 m_err2("Avoid directory names in FILE entity %s: %s",
2244 m_errline("(Use the SEARCH option instead)\n");
2250 m_openchk(&nullfile, "NUL", "w");
2252 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(linux)
2253 m_openchk(&nullfile, "/dev/null", "w");
2255 m_openchk(&nullfile, "nullfile", "w");
2262 idxupdate = ftell(outfile);
2264 /* Include cross-reference file */
2265 strcpy(helpext, ".xrh");
2267 postpreamble = ftell(outfile);
2270 /* Issue error message and text in document when starting an unimplemented
2272 void mb_unimp(eltname)
2275 M_WCHAR *wc_stago, *wc_eltname, *wc_tagc;
2279 fputs("<PARAGRAPH><WEIGHT bold>", outfile);
2280 for (p = m_stago; *p ; p++)
2282 outchar(*p, outfile);
2284 fputs(eltname, outfile);
2285 for (p = m_tagc; *p ; p++)
2287 outchar(*p, outfile);
2289 fprintf(outfile, " not implemented for HelpTag. </WEIGHT></PARAGRAPH>\n\n");
2292 wc_stago = MakeWideCharString(m_stago);
2293 wc_eltname = MakeWideCharString(eltname);
2294 wc_tagc = MakeWideCharString(m_tagc);
2296 m_err3("%s%s%s is not implemented for HelpTag", wc_stago, wc_eltname, wc_tagc);
2298 m_free(wc_stago,"wide character string");
2299 m_free(wc_eltname,"wide character string");
2300 m_free(wc_tagc,"wide character string");
2309 mb_eltname = MakeMByteString(eltname);
2310 mb_unimp(mb_eltname);
2311 m_free(mb_eltname,"multi-byte string");
2315 /* convert user-supplied dimension to scaled points */
2319 double num = 0.0, num2 = 0.0;
2324 if (sscanf(s,"%lf%s%lf",&num, temp, &num2) == 3)
2325 { /* get numeric portion */
2326 M_WCHAR *wc_s, *wc_temp;
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");
2336 while (temp[i] != M_EOS)
2338 if (isupper(temp[i])) temp[i] = tolower(temp[i]);
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"))
2353 m_error("Invalid units: pt assumed");
2357 m_error("No negative dimensions: positive assumed");
2360 return((long) num );
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.
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.
2371 If this routine returns anything other than the empty string (""),
2372 the string returned must be m_free'd.
2375 #if defined(M_PROTO)
2376 GetDefaultHeaderString(
2378 unsigned char desiredType,
2379 char *defaultString )
2381 GetDefaultHeaderString(elementName, desiredType, defaultString)
2383 unsigned char desiredType;
2384 char *defaultString;
2387 unsigned char type,wheredef;
2390 M_WCHAR *wc_elementName;
2394 wc_elementName = MakeWideCharString(elementName);
2395 if (m_lookent(wc_elementName, &type, &content, &wheredef))
2397 if (type == desiredType)
2399 if (type == M_SDATA)
2401 m_free(wc_elementName,"wide character string");
2402 mb_content = MakeMByteString(content);
2405 m_free(mb_content,"multi-byte string");
2413 path = searchforfile(content);
2416 m_err2("Can't find file %s (declared in entity %s)",
2419 m_free(wc_elementName,"wide character string");
2424 m_free(wc_elementName,"wide character string");
2425 return MakeMByteString(path);
2428 m_free(wc_elementName,"wide character string");
2433 m_free(wc_elementName,"wide character string");
2436 retval = m_malloc(strlen(defaultString) + 1,
2437 "GetDefaultHeaderString return");
2438 return strcpy(retval, defaultString);
2446 * Look for an entity by the name of "LanguageElementDefaultLocale".
2447 * If found, set the current locale to be the content of that entity.
2452 unsigned char type,wheredef;
2453 M_WCHAR *elementName;
2457 elementName = MakeWideCharString("LanguageElementDefaultLocale");
2458 if (m_lookent(elementName, &type, &content, &wheredef))
2460 if (type == M_SDATA)
2462 mb_content = MakeMByteString(content);
2463 setlocale(LC_ALL, mb_content);
2464 m_free(mb_content,"multi-byte string");
2467 setlocale(LC_ALL, "");
2470 setlocale(LC_ALL, "");
2471 m_free(elementName,"wide character string");
2473 elementName = MakeWideCharString("LanguageElementDefaultCharset");
2474 if (m_lookent(elementName, &type, &content, &wheredef))
2476 if (type == M_SDATA)
2478 m_free(helpcharset, "help charset");
2479 helpcharset = m_malloc(w_strlen(content) + 1, "help charset");
2480 w_strcpy(helpcharset, content);
2483 m_free(elementName,"wide character string");
2487 #if defined(M_PROTO)
2488 void paragraph(M_WCHAR *indent,
2492 M_WCHAR *ghyperlink,
2494 M_WCHAR *gdescription,
2497 void paragraph(indent,
2509 M_WCHAR *ghyperlink;
2511 M_WCHAR *gdescription;
2517 mbstowcs(xrefstring, "\\<xref paragraph>", 400);
2518 xstrlen = w_strlen(xrefstring);
2519 m_getline(&xrffile, &xrfline);
2520 if (xrffile == NULL)
2522 /* set to primary input source */
2523 xrffile = inputname;
2525 setid(id, TRUE, FALSE, inchapter, chapstring, xrffile, xrfline, FALSE);
2528 char *mb_nodeid, *mb_id;
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");
2540 fputs("<PARAGRAPH", outfile);
2545 mb_id = MakeMByteString(id);
2546 fprintf(outfile, " id %s", mb_id);
2547 m_free(mb_id,"multi-byte string");
2550 if (st4) st4 = FALSE;
2555 " firstindent %d leftindent %d",
2560 handle_link_and_graphic(m_parent(0),
2567 fprintf(outfile, "%s>", listinfo);
2572 #if defined(M_PROTO)
2599 M_WCHAR *ghyperlink,
2601 M_WCHAR *gdescription,
2659 M_WCHAR *ghyperlink;
2661 M_WCHAR *gdescription;
2665 unsigned char etype,wheredef;
2667 GetDefaultHeaderString("FigureElementDefaultHeadingString",
2671 fprintf(outfile, "<PARAGRAPH%s>\n", listinfo);
2674 ftonumber = (!tonumber || (vnumber(tonumber) == NUMBER));
2675 if (id && ! ftonumber)
2677 m_error("Figures with ID's must be numbered");
2680 if (ftonumber) figno++;
2686 mb_number = MakeMByteString(number);
2687 figno = atoi(mb_number);
2688 m_free(mb_number,"multi-byte string");
2691 "Explicit figure number %s inconsistent with NONUMBER option",
2698 char mb_xrefstring[400];
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)
2706 /* set to primary input source */
2707 xrffile = inputname;
2709 setid(id, TRUE, FALSE, inchapter, chapstring, xrffile, xrfline, TRUE);
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
2722 f_contqual[0] = M_EOS;
2724 /* check ENTITY and determine the figure type */
2727 m_lookent(file, &etype, &f_file, &wheredef);
2728 if (etype != M_SYSTEM)
2730 M_WCHAR *wc_stago, *wc_tagc;
2731 M_WCHAR *wc_entsystem, *wc_entkw;
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",
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");
2752 f_content = searchforfile(f_file);
2755 if (getqualified(f_contqual, f_content))
2757 /* unsuccessful qual */
2758 if (w_strlen(f_content) < FNAMELEN)
2759 w_strcpy(f_contqual, f_content);
2762 m_err1("Internal error. File name too long: %s",
2770 m_err2("Can't find file %s (declared in entity %s)",
2779 static M_WCHAR empty = M_EOS;
2781 if (!f_content) f_content = ∅
2783 mb_content = MakeMByteString(f_content);
2784 fprintf(outfile, "<FIGURE file %s", mb_content);
2785 m_free(mb_content,"multi-byte string");
2792 mb_id = MakeMByteString(id);
2793 fprintf(outfile, " id %s", mb_id);
2794 m_free(mb_id,"multi-byte string");
2797 /* handle link specific code */
2799 { /* default to type jump */
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 */
2818 M_WCHAR *wc_stago, *wc_tagc;
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",
2826 m_free(wc_stago,"wide character string");
2827 m_free(wc_tagc,"wide character string");
2832 char *mb_ghyperlink;
2834 mb_ghyperlink = MakeMByteString(ghyperlink);
2835 fprintf(outfile, " link \"%s\"", mb_ghyperlink);
2836 m_free(mb_ghyperlink,"multi-byte string");
2840 if (glinktype || gdescription)
2844 "Error: %sP%s ghyperlink was undefined.\n",
2848 "Error: %sP%s ghyperlink was undefined.\n",
2852 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
2860 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
2867 m_errline("Use ``ghyperlink='' if the value contains non-alphabetics");
2869 fputs(" glink _undefined", outfile);
2875 char *mb_gdescription;
2877 mb_gdescription = MakeMByteString(gdescription);
2878 fprintf(outfile, " description \"%s\"", mb_gdescription);
2879 m_free(mb_gdescription,"multi-byte string");
2881 /* end of link specific code */
2883 /* if caption position is not specified, have it track the figure position */
2888 switch (vcenter(figpos))
2891 fputs(" left", outfile);
2894 fputs(" center", outfile);
2897 fputs(" right", outfile);
2901 switch (vcenter(cappos))
2904 fputs(" cleft", outfile);
2907 fputs(" ccenter", outfile);
2910 fputs(" cright", outfile);
2913 fputs(" ctop>\n", outfile);
2917 fprintf(outfile, "%s %d. ", string, figno);
2919 m_free(string, "default header string return");
2922 #if defined(M_PROTO)
2923 void endterm( M_WCHAR *base, M_WCHAR *gloss, int linktype)
2925 void endterm( base, gloss, linktype)
2932 M_WCHAR wnl, wsp, wus;
2936 mbtowc(&wnl, "\n", 1);
2937 mbtowc(&wsp, " ", 1);
2938 mbtowc(&wus, "_", 1);
2940 /* strip possible newlines out of base form */
2943 for (p = base; *p ; p++)
2945 if (*p == wnl) *p = wsp;
2949 /* terminate the term string */
2950 if (termp - term > MAXTERM) termp = &term[MAXTERM];
2953 /* trim possible last space */
2954 if (termp - term > 1 && *(termp-1) == wsp)
2959 /* Check if it should be entered into the glossary structure */
2960 if (vgloss(gloss) == GLOSS)
2962 m_ntrtrie(base ? base : term, >ree, (M_TRIE *) ENTERTERM);
2963 fprintf(outfile, "<LINK %d \"", linktype);
2964 for (p = base ? base : term; *p; p++)
2968 outchar(wus, outfile);
2972 outchar(wc_toupper(*p), outfile);
2975 fputs("_DEF\">", outfile);
2978 /* Handle the output */
2979 mb_strcode("<WEIGHT bold>", outfile);
2981 if (m_mblevel("EXAMPLESEG") || m_mblevel("IMAGE"))
2983 /* Are we in one of these? */
2984 for(p = term; *p; p++)
2991 for(p = term; *p; p++)
2993 outchar(*p, outfile);
2997 mb_strcode("</WEIGHT>", outfile);
2999 if (vgloss(gloss) == GLOSS)
3001 mb_strcode("</LINK>", outfile);
3004 if (echo) mb_echohead("++");
3007 #if defined(M_PROTO)
3008 M_WCHAR wc_toupper(M_WCHAR wc)
3010 M_WCHAR wc_toupper(wc)
3014 if ((wc >= 0) && (wc <= 255))
3016 return _toupper(wc);