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/5 1998/04/06 13:18:57 mgreess $ */
24 /* Copyright (c) 1986, 1987, 1988, 1989 Hewlett-Packard Co. */
25 /* Miscellaneous Procedures for HP Tag/TeX translator */
32 #include "LocaleXlate.h"
33 #include "XlationSvc.h"
35 void assert_hometopic_exists(M_NOPAR)
37 static const char hometopic[] = "-HOMETOPIC";
38 char id[SDLNAMESIZ + sizeof(hometopic)];
40 GetDefaultHeaderString("UntitledElementDefaultHeadingString",
47 sprintf(id, "%s%s", sdlReservedName, hometopic);
48 mb_starthelpnode("_HOMETOPIC", id, 1);
52 pc = MakeMByteString(savedtitle);
54 "<HEAD CLASS=\"HEAD\" ABBREV=\"%s\"></HEAD>\n</VIRPAGE>\n",
57 m_free(pc, "multi-byte string");
59 m_free(string, "GetDefaultHeaderString return");
62 /* Determine base name for files (i.e., input name without extension).
63 Open output and error files */
64 void fbasename(M_NOPAR)
69 char fileListErr[] = "filelist.err";
74 m_error("Specify input file");
78 if ((m_argc > 2) && (strchr(m_argv[2], 'f') || strchr(m_argv[2], 'F')))
81 /* Get installation directory */
82 #define CONTRIB "/usr/dt/bin/"
84 /* get our path if we can */
85 /* A hacked up ``which'', just to find our directory */
86 /* fills ``install'' with path to ourself */
96 if ( *(m_argv[0]) == '/' )
98 /* fully qualified path to ourself was specified */
99 if (access(m_argv[0],1) == 0)
101 /* if full path name exists and is executable */
102 /* get the dirname */
103 for (p = m_argv[0]; *p ; p++) ; /* end of string, (the hard way) */
104 /* backup to dirsep */
107 if (p < m_argv[0]) m_error("Internal Error.");
108 if (*p == dirsep) break;
110 p++; /* just past the dirsep */
113 install = (char *) m_malloc(strlen(m_argv[0]) + 1,
114 "installation directory");
115 strcpy(install, m_argv[0]);
118 none = 0; /* we've got it. */
122 m_error("Internal Error (which).");
127 /* not fully specified, check each component of path for ourself */
128 snprintf(patbuf, sizeof(patbuf), "%s", getenv("PATH"));
134 cp = strchr(path, ':');
139 sprintf(buf, "%s/%s", path, m_argv[0]);
141 if (access(buf, 1) == 0)
143 install = (char*) m_malloc(strlen(path) + 1,
144 "installation directory");
145 strcpy(install, path);
148 /* else, not an error if we can't find a particular one. */
153 break; /* either out of paths, or we found it. */
160 /* can't get it, use default */
161 install = (char *) m_malloc(strlen(CONTRIB) + 1,
162 "installation directory");
163 strcpy(install, CONTRIB);
165 /* else -- we've got it */
168 /* Set default working directory (from input filename) */
169 for (p = strchr(m_argv[1], M_EOS); p > m_argv[1] ; p--)
170 if (*(p - 1) == dirsep)
176 work = (char *) m_malloc(strlen(m_argv[1]) + 1, "working directory");
177 strcpy(work, m_argv[1]);
178 indir = (char *) m_malloc(strlen(m_argv[1]) + 1, "input directory");
179 strcpy(indir, m_argv[1]);
187 /* Build base name */
188 q = strchr(m_argv[1], M_EOS);
189 while ((q > m_argv[1]) && (*q != '.') && (*q != dirsep))
191 defaultext = (LOGICAL) (*q != '.');
192 if (! defaultext) *q = M_EOS;
193 nodirbase = (char *) m_malloc(strlen(p) + 1,
194 "basename without directory");
195 strcpy(nodirbase, p);
196 /* Get working directory option, if specified */
198 base = (char *) m_malloc(n + strlen(".htg") + 1, "basename");
201 baseext = base + n + 1;
206 options(TRUE); /* pluck only length changing optins */
209 /* Build short versions of basename */
210 /* set up global helpbase and helpext */
211 helpbase = (char *) m_malloc(strlen(work) +
213 PRE_EXTENSION_LIMIT +
217 strcpy(helpbase, work);
218 strncat(helpbase, nodirbase, BASENAME_LIMIT);
219 helpext = helpbase + strlen(helpbase);
222 { /* Build long names */
223 /* set up global helpbase and helpext */
224 helpbase = (char *) m_malloc(strlen(work) +
226 PRE_EXTENSION_LIMIT +
230 strcpy(helpbase, work);
231 strcat(helpbase, nodirbase);
232 helpext = helpbase + strlen(helpbase);
235 /* Open error files */
238 p = mb_malloc(strlen(work)+sizeof(fileListErr));
240 strcat(p, fileListErr);
241 m_openchk(&m_errfile, p, "w");
246 strcpy(helpext, ".err");
247 m_openchk(&m_errfile, helpbase, "w");
252 /* This procedure starts a CHAPTER */
261 char *chapterPrefixString =
262 GetDefaultHeaderString("ChapterElementDefaultHeadingString",
265 char *chapterSuffixString =
266 GetDefaultHeaderString("ChapterSuffixElementDefaultHeadingString",
274 m_itoa(chapter, chapstring);
286 chapterSuffixString);
287 m_free(chapterPrefixString, "GetDefaultHeaderString return");
288 if (*chapterSuffixString)
289 m_free(chapterSuffixString, "GetDefaultHeaderString return");
293 /* Called at end of manual to report terms that occurred in the document
294 but not entered in the glossary */
295 void checkgloss(M_NOPAR)
298 M_WCHAR id[MAXTERM + 1];
299 M_TRIE *node[MAXTERM + 1];
302 if (! gtree.data) return;
304 current = gtree.data;
307 id[n] = current->symbol;
308 node[n] = current->next;
311 if ((intptr_t) current->data >= 0)
312 m_err1("No glossary definition for %s", id);
313 current = current->next;
323 current = current->data;
330 /* End Error Message macro \starterrmsg call, check to see if Error Message
331 head is user specified or default */
332 void checkmsghead(M_NOPAR)
335 GetDefaultHeaderString("MessagesElementDefaultHeadingString",
338 if (emsghead == DEFHEAD)
339 { /* head not output yet */
340 fprintf(outfile, "<HEAD CLASS=\"HEAD\">%s</HEAD>\n", string);
343 else if (emsghead == USERHEAD)
344 { /* user specified head */
347 m_free(string, "GetDefaultHeaderString return");
348 } /* end checkmsghead() */
351 /* construct a qualified file name */
353 static int mb_getqualified(char *qualname, char *unqualname)
355 static int mb_getqualified(qualname, unqualname)
360 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(__osf__) || defined(linux) || defined(CSRG_BASED)
364 char tokstr [ 20 ], *gp, *p, *pp, *fnp, curdir[FNAMELEN-1];
365 int roomleft = FNAMELEN - 1;
373 if (strlen(unqualname) < (size_t) FNAMELEN)
374 strcpy(fn, unqualname );
377 m_mberr1("Internal Error. File name too long for qualifying: %s",
384 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(__osf__) || defined(linux) || defined(CSRG_BASED)
386 gp = qualname + strlen(qualname);
387 roomleft = roomleft - strlen(qualname);
389 /* if path is from root, tack that on, else tack on the current
390 directory (for the referenced drive, if MS-DOS) */
391 /* We assume FNAMELEN is at least three (3), so no range checking here */
394 strcat(qualname, SSEP);
400 f = popen("/bin/pwd", "r");
403 if (strlen(gp) >= (size_t) roomleft)
405 m_mberr1("Internal error: possible stray pointer in getqualified(): %s",
409 strcat(qualname,SSEP);
413 /* if MS-DOS, force to upper case, then get drive spec */
415 if ( fn[1] == ':' ) {
416 strncpy ( qualname, fn, 2 );
420 getcwd(qualname, roomleft);
423 gp = qualname + strlen ( qualname );
424 roomleft = roomleft - strlen ( qualname );
425 /* if path is from root, tack that on, else tack on the current
426 directory (for the referenced drive, if MS-DOS) */
427 if ( *fnp == CSEP ) {
428 strcat ( qualname, SSEP );
433 /* assume current directory always !!! */
435 getcwd(curdir, FNAMELEN-1);
436 if (*curdir != *qualname) {
437 m_err1("Relative directory %s for non-current drive, can't qualify",
441 if (strlen(curdir) > 3) {
442 if ((strlen(curdir+3)+1) < roomleft) { /* "1" for SSEP */
443 strcpy( gp+1, curdir+3 );
444 strcat ( qualname, SSEP );
445 roomleft = roomleft - strlen(curdir+3) - 1; /* "1" for SSEP */
448 m_err1("Internal error. File name too long for qualifying: %s",
456 strcpy(tokstr, " \r\n\t");
457 strcat(tokstr, SSEP);
460 p = strtok(( p == NULL ) ? fnp : NULL, tokstr);
461 if ( p == NULL ) break;
462 if ( *p == '.' ) /* alias */
464 if ( *(p+1) == '.' ) /* parent */
466 *strrchr(qualname, CSEP) = '\0';
467 pp = strrchr(qualname, CSEP);
468 if (pp == NULL) /* FAIL */
470 m_mberr1("Internal error. Failed in qualifying %s", unqualname);
481 if ((strlen(p)+1) < (size_t) roomleft)
484 strcat(qualname, SSEP);
485 roomleft = roomleft - strlen(p) - 1;
489 m_mberr1("Internal error. File name too long for qualifying: %s",
496 *strrchr(qualname, CSEP) = '\0';
498 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(__osf__) || defined(linux) || defined(CSRG_BASED)
504 } /* end mb_getqualified */
507 int getqualified (qualname, unqualname)
512 char mb_qualname[FNAMELEN],
513 mb_unqualname[FNAMELEN];
515 wcstombs(mb_qualname, qualname, FNAMELEN);
516 wcstombs(mb_unqualname, unqualname, FNAMELEN);
518 retval = mb_getqualified(mb_qualname, mb_unqualname);
520 mbstowcs(qualname, mb_qualname, FNAMELEN);
521 mbstowcs(unqualname, mb_unqualname, FNAMELEN);
527 /* handle the common link and graphic code for <p> and <image> */
529 handle_link_and_graphic(parent,
535 M_WCHAR *parent, *gentity, *gposition, *ghyperlink, *glinktype, *gdescription;
537 unsigned char etype, wheredef;
538 char *mb_content, *ssi, id[32];
539 static M_WCHAR empty = M_EOS;
542 /* handle graphic specific code */
543 /* initialize some stuff first:
544 - file is the entity name,
545 - f_file is the content of the entity, used only if f_content nonNULL
546 - f_content is f_file with the relative pathname, initialized to NULL,
547 - f_contqual is fully qualified f_file, assigned ONLY IF
552 f_contqual[0] = M_EOS;
554 /* get the position, default to left */
558 M_WCHAR *wc_left, *wc_right;
560 wc_right = MakeWideCharString(QRIGHT);
561 if (!m_wcupstrcmp(gposition, wc_right))
567 wc_left = MakeWideCharString(QLEFT);
568 if (m_wcupstrcmp(gposition, wc_left))
570 m_err1("Invalid value for gposition: `%s'", gposition);
572 m_free(wc_left,"wide character string");
574 m_free(wc_right,"wide character string");
577 /* check ENTITY and determine the figure type */
580 m_lookent(gentity, &etype, &f_file, &wheredef);
581 if (etype != M_SYSTEM)
583 M_WCHAR *wc_entsystem, *wc_entkw, *wc_stago, *wc_tagc;
585 wc_entsystem = MakeWideCharString(m_entsystem);
586 wc_entkw = MakeWideCharString(m_entkw);
587 wc_stago = MakeWideCharString(m_stago);
588 wc_tagc = MakeWideCharString(m_tagc);
590 "%s not a %s %s, as required for the ENTITY parameter of %s%s%s",
597 m_free(wc_entsystem,"wide character string");
598 m_free(wc_entkw,"wide character string");
599 m_free(wc_stago,"wide character string");
600 m_free(wc_tagc,"wide character string");
605 f_content = searchforfile(f_file);
608 if (getqualified(f_contqual, f_content))
610 /* unsuccessful qual */
611 if (w_strlen(f_content) < FNAMELEN)
612 w_strcpy(f_contqual, f_content);
615 m_err1("Internal error. File name too long: %s",
623 m_err2("Can't find file %s (declared in entity %s)",
628 if (!f_content) f_content = ∅
630 mb_content = MakeMByteString(f_content);
631 sprintf(id, "%s%d", sdlReservedName, NextId());
632 ssi = MakeMByteString(m_parent(0));
633 fprintf(outfile, "<HEAD SSI=\"%s-GRAPHIC-%s\">", ssi, leftright);
635 HandleLink(ghyperlink, glinktype, gdescription);
636 fprintf(outfile, "<SNREF>\n<REFITEM RID=\"%s\" ", id);
637 fputs("CLASS=\"FIGURE\"", outfile);
638 AddToSNB(id, mb_content);
639 m_free(mb_content,"multi-byte string");
642 /* and finish the position now */
645 fprintf(outfile, " SSI=\"GRPH-%s\"", leftright);
650 fputs("></REFITEM></SNREF>", outfile);
652 fputs("</LINK>", outfile);
653 fputs("</HEAD>", outfile);
656 if (!ghyperlink && (glinktype || gdescription))
660 "Error: %sP%s ghyperlink was undefined.\n",
664 "Error: %sP%s ghyperlink was undefined.\n",
668 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
676 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
683 m_errline("Use ``ghyperlink='' if the value contains non-alphabetics");
688 /* Process an item in a list */
690 void Item(M_WCHAR *id)
696 char orderString[32];
697 static char *ROMAN0[] =
698 {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
699 static char *ROMAN10[] =
700 {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
701 static char *ROMAN100[] =
702 {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
703 static char ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
704 static char *roman0[] =
705 {"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"};
706 static char *roman10[] =
707 {"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"};
708 static char *roman100[] =
709 {"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"};
710 static char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
711 static char numbers[] = "0123456789";
712 static char romanString[] = "ROMAN";
713 static char alphaString[] = "ALPHA";
714 static char arabicString[] = "ARABIC";
715 int count, metaCount;
717 char label_id[SDLNAMESIZ+10];
722 LOGICAL isBullet, isLoose, isFirst;
726 if (listitems[list].firstitem)
728 listitems[list].firstitem = FALSE;
731 count = ++lastlist->lastlist->count;
732 if (count > 999) count = 999; /* holy cow! Big list. */
743 if (lastlist->lastlist->space == TIGHT)
752 listtype = lastlist->lastlist->type;
753 if (listtype == BULLET)
756 if ((listtype != PLAIN) && (listtype != MILSPEC))
757 { /* don't emit label for type==PLAIN and type==MILSPEC */
763 pThisBulletId = &firstLooseBulletId;
766 looseBulletIdIndex = (- looseBulletIdIndex) + 1;
767 pThisBulletId = &looseBulletId[looseBulletIdIndex];
773 pThisBulletId = &firstBulletId;
776 bulletIdIndex = (- bulletIdIndex) + 1;
777 pThisBulletId = &bulletId[bulletIdIndex];
781 { /* use an existing block containing a bullet */
782 strcpy(label_id, sdlReservedName);
783 m_itoa(*pThisBulletId, label_id + SDLNAMESIZ - 1);
787 *pThisBulletId = NextId();
788 strcpy(label_id, sdlReservedName);
789 m_itoa(*pThisBulletId, label_id + SDLNAMESIZ - 1);
792 fputs("<FDATA>\n", outfile);
796 "<BLOCK ID=\"%s\" CLASS=\"ITEM\" TIMING=\"ASYNC\" ",
799 "SSI=\"%s%s-BULLET\">\n<P><SPC NAME=\"[bull ]\">",
802 fputs("</P>\n</BLOCK>\n", outfile);
807 strcpy(label_id, sdlReservedName);
808 m_itoa(NextId(), label_id + SDLNAMESIZ - 1);
811 fputs("<FDATA>\n", outfile);
814 fprintf(outfile, "<BLOCK ID=\"%s\" CLASS=\"ITEM\" SSI=\"", label_id);
819 if (listtype == ORDER)
821 orderString[0] = '\0';
822 switch (lastlist->lastlist->order)
825 snprintf(orderString, sizeof(orderString), "%s%s%s", ROMAN100[count / 100], ROMAN10[(count / 10) % 10], ROMAN0[count % 10]);
830 while ((count -= 26) > 0) metaCount++;
831 count = lastlist->lastlist->count;
832 if (count > 999) count = 999;
835 while (--metaCount >= 0) strncat(orderString, &ALPHABET[count], 1);
839 if (metaCount = (count / 100))
840 strncat(orderString, &numbers[metaCount], 1);
841 if (metaCount || ((count / 10) % 10))
842 strncat(orderString, &numbers[(count / 10) % 10], 1);
843 strncat(orderString, &numbers[count % 10], 1);
847 snprintf(orderString, sizeof(orderString), "%s%s%s", roman100[count / 100], roman10[(count / 10) % 10], roman0[count % 10]);
852 while ((count -= 26) > 0) metaCount++;
853 count = lastlist->lastlist->count;
854 if (count > 999) count = 999;
857 while (--metaCount >= 0) strncat(orderString, &alphabet[count], 1);
862 "%s%s-%s\">\n<P>%s%c",
867 lastlist->lastlist->punct == DOTPUNCT ? '.' : ')' );
873 sprintf(buffer, "Item %s", orderString);
874 wc = MakeWideCharString(buffer);
875 w_strcpy(xrefstring, wc);
876 m_free(wc,"wide character string");
878 xstrlen = w_strlen(xrefstring);
879 m_getline(&xrffile, &xrfline);
882 /* set to primary input */
894 item_id = MakeMByteString(id);
898 { /* Bullet, Check or Plain list */
899 if (id) m_error("Cross-reference ID in non-ORDER list not allowed");
900 /* already handled Bullet */
901 if (listtype == CHECK)
904 "%s%s-CHECK\">\n<P><SPC NAME=\"[check ]\">",
908 /* don't emit label for listtype==PLAIN and listtype==MILSPEC */
911 if ((listtype != PLAIN) && (listtype != MILSPEC) && (listtype != BULLET))
912 fputs("</P>\n</BLOCK>\n", outfile);
914 sprintf(ssi, "%s%s", first, loose);
915 if ((listtype == PLAIN) || (listtype == MILSPEC))
916 PushForm("ITEM", ssi, item_id);
918 PushForm2("ITEM", ssi, label_id, item_id);
921 m_free(item_id, "multi-byte string");
933 } /* END procedure rsectstart */
936 /* Called at the end of a chapter, appendix, or section to end an open
937 sequence of rsects */
938 void rseqend(M_NOPAR)
946 /* Follow search path to find a file, returning qualified name */
947 M_WCHAR *searchforfile(file)
952 char *mb_file, mb_filename[2048];
953 int dir_leng,file_leng;
955 mb_file = MakeMByteString(file);
956 if (! access(mb_file, READABLE))
958 filename = (M_WCHAR *)
959 m_malloc(w_strlen(file) + 1, "figure/icon filename");
960 w_strcpy(filename, file);
961 m_free(mb_file,"multi-byte string");
965 file_leng = strlen(mb_file);
966 for (searchp = path; searchp ; searchp = searchp->next)
968 if (((dir_leng = strlen(searchp->directory)) + file_leng) >= 2048)
972 wc = MakeWideCharString(searchp->directory);
973 m_err2("%s and %s overflow the file name space", wc, file);
974 m_free(wc,"wide character string");
977 strcpy(mb_filename, searchp->directory);
978 strcpy(mb_filename+dir_leng, mb_file);
979 if (! access(mb_filename, READABLE))
981 m_free(mb_file,"multi-byte string");
982 return(MakeWideCharString(mb_filename));
986 m_free(mb_file,"multi-byte string");
991 /* Start a new helpnode */
993 void starthelpnode(M_WCHAR *ssi,
997 void starthelpnode(ssi, id, level)
1004 char *mbyte, *mb_ssi;
1005 char mb_nodeid[NODEID_LENGTH+1], nodenum[32];
1007 if (outfile != m_outfile)
1009 m_error("Internal warning: Outfile has been redirected.");
1015 mb_ssi = MakeMByteString(ssi);
1017 /* we can't use the bullet block across virpage boundaries */
1020 looseBulletId[0] = 0;
1021 looseBulletId[1] = 0;
1023 firstLooseBulletId = 0;
1025 /* might as well always start with id 0 (we flip first) */
1027 looseBulletIdIndex = 1;
1029 if ((id == NULL) || (*id == 0))
1031 strcpy(mb_nodeid, sdlReservedName);
1032 m_itoa(NextId(), nodenum);
1033 strcpy(mb_nodeid + SDLNAMESIZ - 1, nodenum);
1034 mbstowcs(nodeid, mb_nodeid, NODEID_LENGTH);
1038 w_strncpy(nodeid, id, NODEID_LENGTH);
1039 wcstombs(mb_nodeid, id, NODEID_LENGTH);
1043 "<VIRPAGE ID=\"%s\" LEVEL=\"%d\" LANGUAGE=\"%s\" CHARSET=\"%s\" DOC-ID=\"%s\" SSI=\"%s\">\n",
1050 m_free(mb_ssi,"multi-byte string");
1051 snbstart = ftell(outfile);
1052 } /* End starthelpnode(id) */
1055 #if defined(M_PROTO)
1056 void mb_starthelpnode(char *ssi,
1060 void mb_starthelpnode(ssi, id, level)
1066 M_WCHAR *wc_ssi, *wc_id;
1070 wc_ssi = MakeWideCharString(ssi);
1073 wc_id = MakeWideCharString(id);
1074 starthelpnode(wc_ssi, wc_id, level);
1076 m_free(wc_ssi,"wide character string");
1078 m_free(wc_id,"wide character string");
1082 /* Start a labeled list */
1083 void StartLabList(spacing, longlabel)
1088 static char def_spacing[] = "LOOSE";
1091 if (list >= MAXLISTLEV)
1092 m_error("Nesting of <LIST> and <LABLIST> too deep");
1095 mb_spacing = MakeMByteString(spacing);
1097 mb_spacing = def_spacing;
1099 sprintf(ssi, "LABELED-%s", mb_spacing);
1100 PushForm("LIST", ssi, NULL);
1102 if (mb_spacing != def_spacing)
1103 mb_free(&mb_spacing);
1107 listitems[list].firstitem = TRUE;
1108 listitems[list].longlabel = vlonglabel(longlabel);
1110 if (list <= MAXLISTLEV)
1112 if (vspacing(spacing) == TIGHT)
1114 lablisttight[list] = TRUE;
1118 lablisttight[list] = FALSE;
1125 #if defined(M_PROTO)
1126 void StartList(M_WCHAR *type,
1131 void StartList(type, order, spacing, cont)
1132 M_WCHAR *type, *order, *spacing, *cont;
1140 static char def_spacing[] = "LOOSE";
1146 mb_spacing = MakeMByteString(spacing);
1150 mb_spacing = def_spacing;
1155 if (list > MAXLISTLEV)
1156 m_error("Nesting of <LIST> and <LABLIST> too deep");
1158 if (! lastlist->started && cont)
1160 m_error("No previous list to continue");
1166 if (order && (vordertype(order) != lastlist->order))
1168 m_error("Unable to continue a list and change the numbering scheme");
1172 if (type && (vtype(type) != lastlist->type))
1174 m_error("Unable to continue a list and change its type");
1180 { /* clear old list? */
1181 for (chain = lastlist->chain; chain ; chain = xchain)
1183 xchain = chain->next;
1184 m_free(chain, "list chain");
1186 lastlist->chain = NULL;
1187 lastlist->count = 0;
1190 /* If outermost list, initialize according to current defaults */
1191 if (! cont && lastlist == &outlist)
1193 outlist.type = vtype(NULL);
1194 outlist.order = vordertype(NULL);
1196 outlist.space = vspacing(NULL);
1197 outlist.punct = DOTPUNCT;
1200 if (type) lastlist->type = vtype(type);
1204 lastlist->type = ORDER;
1205 lastlist->order = vordertype(order);
1208 switch (lastlist->type)
1212 list_type = "PLAIN";
1215 list_type = "CHECK";
1218 list_type = "ORDER";
1222 list_type = "BULLET";
1224 sprintf(ssi, "%s-%s", list_type, mb_spacing);
1226 PushForm("LIST", ssi, NULL);
1228 if (mb_spacing != def_spacing)
1229 m_free(mb_spacing, "multi-byte string");
1232 lastlist->space = LOOSE;
1233 if (spacing && ! m_wcmbupstrcmp(spacing, QTIGHT)) lastlist->space = TIGHT;
1235 if (type && order && m_wcmbupstrcmp(type, QORDER))
1236 m_err2("Incompatible specification for list: %s and %s", type, order);
1238 if (lastlist->type == ORDER)
1240 chain = (CONTCHAIN *) m_malloc(sizeof(CONTCHAIN), "list chain");
1241 chain->next = lastlist->chain;
1242 lastlist->chain = chain;
1243 chain->where = ftell(outfile);
1246 lastlist->started = TRUE;
1247 listitems[list].firstitem = TRUE;
1249 /* Prepare for sublist */
1250 nextlist = (LIST *) m_malloc(sizeof(LIST), "list structure");
1251 nextlist->lastlist = lastlist;
1252 nextlist->type = lastlist->type;
1253 nextlist->punct = lastlist->punct;
1254 if (lastlist->type == ORDER)
1256 nextlist->order = lastlist->order + 1;
1257 if (nextlist->order > LROMAN)
1259 nextlist->order = ARABIC;
1260 nextlist->punct = PARENPUNCT;
1263 else nextlist->order = lastlist->order;
1264 nextlist->count = 0;
1265 nextlist->space = lastlist->space;
1266 nextlist->started = FALSE;
1267 nextlist->where = FIRST;
1268 nextlist->chain = NULL;
1269 lastlist = nextlist;
1276 CONTCHAIN *chain, *xchain ;
1279 curlist = lastlist->lastlist ;
1281 if ((curlist->type == PLAIN) || (curlist->type == MILSPEC))
1288 for (chain = lastlist->chain ; chain ; chain = xchain)
1290 xchain = chain->next ;
1291 m_free(chain, "list chain") ;
1293 m_free(lastlist, "list structure") ;
1294 lastlist = curlist ;
1295 for (chain = lastlist->chain ; chain ; chain = chain->next)
1297 if (lastlist->count > 999)
1299 m_error("Unable to support more than 999 items in an ordered list") ;
1300 lastlist->count = 999 ;
1303 if (lastlist->type == BULLET) bulcount-- ;
1307 /* Open and initialize TeX file */
1308 void texinit(M_NOPAR)
1310 LOGICAL init = TRUE;
1313 unsigned char wheredef;
1324 /* Check .XRF file */
1325 strcpy(helpext, ".xrh");
1326 xrf = fopen(helpbase, "r");
1327 if (! xrf) rebuild = TRUE;
1330 fscanf(xrf, "\\gobble\001");
1331 for (p = m_signon; *p ; p++)
1337 "Output files from different version of Tag, regenerating. . .\n");
1346 while ((ic = getc(xrf)) != EOF)
1347 if (ic == '\n') break;
1348 if (xrf && ic !=EOF)
1349 while ((ic = getc(xrf)) != EOF)
1350 if (ic == '\n') break;
1354 /* Open output files */
1355 strcpy(helpext, ".sdl");
1356 m_openchk(&m_outfile, helpbase, "w");
1357 outfile = m_outfile;
1359 savehelpfilename = (M_WCHAR *)m_malloc(strlen(helpbase)+1, "help file name");
1360 mbstowcs(savehelpfilename, helpbase, strlen(helpbase) + 1);
1363 strcpy(helpext, ".idx");
1364 m_openchk(&indexfp, helpbase, "wb");
1366 /* system notation block file */
1367 strcpy(helpext, ".snb");
1368 m_openchk(&snbfp, helpbase, "wb");
1370 while (name = m_cyclent(init, &type, &content, &wheredef))
1376 if (type == M_SYSTEM)
1377 qfile = searchforfile(content);
1379 if (qfile) m_free(qfile, "figure filename");
1381 if (type == M_SYSTEM)
1383 mbtowc(&wsl, "/", 1);
1385 if (w_strchr(content, wsl))
1387 m_err2("Avoid directory names in FILE entity %s: %s",
1390 m_errline("(Use the SEARCH option instead)\n");
1395 /* Include cross-reference file */
1396 strcpy(helpext, ".xrh");
1398 postpreamble = ftell(outfile);
1402 /* Lookup localized header string entity as defined (by default) in
1403 locallang.ent. If the the header string was not found, or it was
1404 not of type "desiredType", return the default.
1406 If the entity is of type file (M_SYSTEM) then if the content is not
1407 empty search the path for the file. If the file is found, return
1408 its name else return an empty string.
1410 If this routine returns anything other than the empty string (""),
1411 the string returned must be m_free'd.
1414 #if defined(M_PROTO)
1415 GetDefaultHeaderString(
1417 unsigned char desiredType,
1418 char *defaultString )
1420 GetDefaultHeaderString(elementName, desiredType, defaultString)
1422 unsigned char desiredType;
1423 char *defaultString;
1426 unsigned char type,wheredef;
1429 M_WCHAR *wc_elementName;
1433 wc_elementName = MakeWideCharString(elementName);
1434 if (m_lookent(wc_elementName, &type, &content, &wheredef))
1436 if (type == desiredType)
1438 if (type == M_SDATA)
1440 m_free(wc_elementName,"wide character string");
1441 mb_content = MakeMByteString(content);
1444 m_free(mb_content,"multi-byte string");
1452 path = searchforfile(content);
1455 m_err2("Can't find file %s (declared in entity %s)",
1458 m_free(wc_elementName,"wide character string");
1463 m_free(wc_elementName,"wide character string");
1464 return MakeMByteString(path);
1467 m_free(wc_elementName,"wide character string");
1472 m_free(wc_elementName,"wide character string");
1475 retval = m_malloc(strlen(defaultString) + 1,
1476 "GetDefaultHeaderString return");
1477 return strcpy(retval, defaultString);
1484 /* A function that takes a language/charset pair and:
1485 * if they are standard, leave them unchanged but get local
1486 * versions and setlocale(3) using those
1487 * if they are local, setlocale(3) with them and replace them with
1488 * standard versions.
1491 #if defined(M_PROTO)
1492 SetStdLocale(char *pLang, char *pCharset)
1494 SetStdLocale(pLang, pCharset)
1499 static const char *cString = "C";
1500 static const char *isoString = "ISO-8859-1";
1501 _DtXlateDb myDb = NULL;
1502 char myPlatform[_DtPLATFORM_MAX_LEN+1];
1503 char myLocale[256]; /* arbitrarily large */
1504 char myLocaleTemp[sizeof(myLocale)]; /* non-arbitrarily the same */
1512 snprintf(myLocale, sizeof(myLocale), "%s", pLang);
1515 snprintf(myLocaleTemp, sizeof(myLocaleTemp), "%s.%s", myLocale, pCharset);
1516 strcpy(myLocale, myLocaleTemp);
1519 if ((_DtLcxOpenAllDbs(&myDb) != 0) ||
1520 (_DtXlateGetXlateEnv(myDb,myPlatform,&execVer,&compVer) != 0))
1523 "Warning: could not open locale translation database.\n");
1524 if (m_errfile != stderr)
1526 "Warning: could not open locale translation database.\n");
1527 strcpy(pLang, cString);
1528 strcpy(pCharset, isoString);
1530 _DtLcxCloseDb(&myDb);
1534 isStd = !_DtLcxXlateOpToStd(myDb,
1545 { /* already standard - get local versions and set locale */
1546 if (_DtLcxXlateStdToOp(myDb,
1549 DtLCX_OPER_SETLOCALE,
1557 "Warning: could not translate CDE locale to local\n");
1558 if (m_errfile != stderr)
1560 "Warning: could not translate CDE locale to local\n");
1561 strcpy(pLang, cString);
1562 strcpy(pCharset, isoString);
1563 _DtLcxCloseDb(&myDb);
1568 setlocale(LC_CTYPE, locale);
1573 { /* already local - set locale and get standard versions */
1574 if (_DtLcxXlateOpToStd(myDb,
1577 DtLCX_OPER_SETLOCALE,
1585 "Warning: could not translate local locale to CDE\n");
1586 if (m_errfile != stderr)
1588 "Warning: could not translate local locale to CDE\n");
1589 strcpy(pLang, cString);
1590 strcpy(pCharset, isoString);
1591 _DtLcxCloseDb(&myDb);
1594 setlocale(LC_CTYPE, myLocale);
1598 strcpy(pLang, lang);
1602 strcpy(pLang, cString);
1606 strcpy(pCharset, charset);
1609 strcpy(pCharset, isoString);
1613 _DtLcxCloseDb(&myDb);
1619 /* A function that takes the return value from a call to setlocale()
1620 * and extracts the langterr.charset data from it in a vendor neutral
1624 #if defined(M_PROTO)
1630 static char buffer[256];
1631 static char *cString = "C";
1632 _DtXlateDb myDb = NULL;
1633 char myPlatform[_DtPLATFORM_MAX_LEN+1];
1639 if ((_DtLcxOpenAllDbs(&myDb) == 0) &&
1640 (_DtXlateGetXlateEnv(myDb,myPlatform,&execVer,&compVer) != 0))
1643 "Warning: could not open locale translation database.\n");
1644 if (m_errfile != stderr)
1646 "Warning: could not open locale translation database.\n");
1650 if (_DtLcxXlateOpToStd(myDb,
1653 DtLCX_OPER_SETLOCALE,
1654 setlocale(LC_ALL, NULL),
1661 "Warning: could not translate local locale to CDE\n");
1662 if (m_errfile != stderr)
1664 "Warning: could not translate local locale to CDE\n");
1665 _DtLcxCloseDb(&myDb);
1669 if (_DtLcxXlateStdToOp(myDb,
1672 DtLCX_OPER_SETLOCALE,
1680 "Warning: could not translate CDE locale to local\n");
1681 if (m_errfile != stderr)
1683 "Warning: could not translate CDE locale to local\n");
1684 mb_free(&stdLocale);
1685 _DtLcxCloseDb(&myDb);
1689 _DtLcxCloseDb(&myDb);
1691 strcpy(buffer, opLocale);
1692 mb_free(&stdLocale);
1699 * Look for a entities by the name of "LanguageElementDefaultLocale".
1700 * and "LanguageElementDefaultCharset". If not found, get the user's
1701 * locale. If LanguageElementDefaultCharset was set, use that in
1702 * place of the charset of the local (if any). Call SetStdLocale()
1703 * to insure the language and charset are in the normalized form.
1704 * SetStdLocale() will also set the current locale to the local
1705 * versions of the language and charset.
1710 unsigned char type,wheredef;
1711 M_WCHAR *elementName;
1717 char stdLang[256]; /* arbitrarily large */
1718 char stdCharset[256]; /* arbitrarily large */
1726 elementName = MakeWideCharString("LanguageElementDefaultLocale");
1727 if (m_lookent(elementName, &type, &content, &wheredef))
1729 if (type == M_SDATA)
1731 locale = MakeMByteString(content);
1734 m_free(elementName,"wide character string");
1738 tmpStr = GetStdLocale();
1739 locale = mb_malloc(strlen(tmpStr)+1);
1740 strcpy(locale, tmpStr);
1743 dotPtr = strchr(locale, '.');
1747 charset = MakeMByteString(helpcharset);
1748 m_free(helpcharset, "help charset");
1753 elementName = MakeWideCharString("LanguageElementDefaultCharset");
1754 if (m_lookent(elementName, &type, &content, &wheredef))
1756 if (type == M_SDATA)
1758 charset = MakeMByteString(content);
1761 m_free(elementName,"wide character string");
1767 charset = dotPtr + 1;
1772 snprintf(stdLang, sizeof(stdLang), "%s", locale);
1774 snprintf(stdCharset, sizeof(stdCharset), "%s", charset);
1775 SetStdLocale(stdLang, stdCharset);
1778 helpcharset = MakeWideCharString(stdCharset);
1779 helplang = MakeWideCharString(stdLang);
1782 if (charset && (charset != (dotPtr+1)))
1787 #if defined(M_PROTO)
1788 void paragraph(M_WCHAR *indent,
1792 M_WCHAR *ghyperlink,
1794 M_WCHAR *gdescription)
1796 void paragraph(indent,
1807 M_WCHAR *ghyperlink;
1809 M_WCHAR *gdescription;
1812 char *firstString, *indentString;
1816 savid = checkid(id);
1821 StartBlock(NULL, NULL, NULL);
1822 fputs("<P", outfile);
1827 mb_id = MakeMByteString(id);
1828 fprintf(outfile, " ID=\"%s\"", mb_id);
1829 m_free(mb_id,"multi-byte string");
1836 firstPInBlock = FALSE;
1841 indentString = "-INDENT";
1843 fprintf(outfile, " SSI=\"P%s%s\">", firstString, indentString);
1845 handle_link_and_graphic(m_parent(0),
1854 #if defined(M_PROTO)
1862 M_WCHAR *ghyperlink,
1864 M_WCHAR *gdescription)
1883 M_WCHAR *ghyperlink;
1885 M_WCHAR *gdescription;
1889 unsigned char etype,wheredef;
1891 GetDefaultHeaderString("FigureElementDefaultHeadingString",
1897 fputs("<FDATA>\n", outfile);
1901 StartBlock(NULL, NULL, NULL);
1904 fputs("<P SSI=\"FIGURE\">\n", outfile);
1908 HandleLink(ghyperlink, glinktype, gdescription);
1910 else if (glinktype || gdescription)
1914 "Error: %sP%s ghyperlink was undefined.\n",
1918 "Error: %sP%s ghyperlink was undefined.\n",
1922 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
1930 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
1937 m_errline("Use ``ghyperlink='' if the value contains non-alphabetics");
1940 /* end of link specific code */
1943 ftonumber = (!tonumber || (vnumber(tonumber) == NUMBER));
1944 if (id && ! ftonumber)
1946 m_error("Figures with ID's must be numbered");
1949 if (ftonumber) figno++;
1955 mb_number = MakeMByteString(number);
1956 figno = atoi(mb_number);
1957 m_free(mb_number,"multi-byte string");
1959 m_err1("Explicit figure number %s inconsistent with NONUMBER option",
1966 char mb_xrefstring[400];
1968 sprintf(mb_xrefstring, "%s %d", string, figno);
1969 mbstowcs(xrefstring, mb_xrefstring, 400);
1970 xstrlen = w_strlen(xrefstring);
1971 m_getline(&xrffile, &xrfline);
1972 if (xrffile == NULL)
1974 /* set to primary input source */
1975 xrffile = inputname;
1977 setid(id, TRUE, FALSE, inchapter, chapstring, xrffile, xrfline, TRUE);
1980 /* initialize some stuff first:
1981 - file is the entity name,
1982 - f_file is the content of the entity,
1983 used only if f_content nonNULL
1984 - f_content is f_file with the relative pathname, initialized to NULL,
1985 - f_contqual is fully qualified f_file, assigned ONLY IF
1990 f_contqual[0] = M_EOS;
1992 /* check ENTITY and determine the figure type */
1995 m_lookent(file, &etype, &f_file, &wheredef);
1996 if (etype != M_SYSTEM)
1998 M_WCHAR *wc_stago, *wc_tagc;
1999 M_WCHAR *wc_entsystem, *wc_entkw;
2001 wc_stago = MakeWideCharString(m_stago);
2002 wc_tagc = MakeWideCharString(m_tagc);
2003 wc_entsystem = MakeWideCharString(m_entsystem);
2004 wc_entkw = MakeWideCharString(m_entkw);
2005 m_err6("%s not a %s %s, as required for the ENTITY parameter of %s%s%s",
2012 m_free(wc_stago,"wide character string");
2013 m_free(wc_tagc,"wide character string");
2014 m_free(wc_entsystem,"wide character string");
2015 m_free(wc_entkw,"wide character string");
2020 f_content = searchforfile(f_file);
2023 if (getqualified(f_contqual, f_content))
2025 /* unsuccessful qual */
2026 if (w_strlen(f_content) < FNAMELEN)
2027 w_strcpy(f_contqual, f_content);
2030 m_err1("Internal error. File name too long: %s",
2038 m_err2("Can't find file %s (declared in entity %s)",
2045 sprintf(snb_id, "%s%d", sdlReservedName, NextId());
2048 static M_WCHAR empty = M_EOS;
2051 if (!f_content) f_content = ∅
2053 mb_content = MakeMByteString(f_content);
2054 AddToSNB(snb_id, mb_content);
2055 m_free(mb_content,"multi-byte string");
2058 fputs("<SNREF", outfile);
2064 mb_id = MakeMByteString(id);
2065 fprintf(outfile, " ID=\"%s\"", mb_id);
2066 m_free(mb_id,"multi-byte string");
2068 fprintf(outfile, ">\n<REFITEM RID=\"%s\" CLASS=\"FIGURE\" SSI=\"FIG", snb_id);
2071 /* if caption position is not specified, have it track the figure position */
2076 switch (vcenter(figpos))
2079 fputs("-LEFT", outfile);
2082 fputs("-CENTER", outfile);
2085 fputs("-RIGHT", outfile);
2088 fputs("\">\n", outfile);
2092 switch (vcenter(cappos))
2095 capposition = "-LEFT";
2098 capposition = "-CENTER";
2101 capposition = "-RIGHT";
2108 "<HEAD TYPE=\"LINED\" CLASS=\"CAPTION\" SSI=\"NUMBER%s\">%s %d.",
2113 m_free(string, "default header string return");
2116 #if defined(M_PROTO)
2117 void endterm(M_WCHAR *base, M_WCHAR *gloss, char *linktype)
2119 void endterm( base, gloss, linktype)
2126 M_WCHAR dterm[MAXTERM+1];
2128 char buffer[BIGBUF];
2131 if (!(m_mblevel("HEAD") ||
2132 m_mblevel("EXAMPLESEG") ||
2133 m_mblevel("ANNOTATION")
2137 /* Don't re-enable output yet if in a <HEAD>, <EX> or <ANNOTATION> */
2141 mbtowc(&wnl, "\n", 1);
2142 mbtowc(&wsp, " ", 1);
2144 /* terminate the term string */
2145 if (termp - term > MAXTERM) termp = &term[MAXTERM];
2148 /* make a copy - will transform to match definition transformations */
2149 w_strcpy(dterm, term);
2150 termp = dterm + (termp - term);
2152 /* Check if it should be entered into the glossary structure */
2153 if (vgloss(gloss) == GLOSS)
2155 /* strip possible newlines out of base form */
2158 for (p = base; *p ; p++)
2160 if ((p - base) >= MAXTERM)
2162 if ((p - base) == MAXTERM)
2164 M_WCHAR *wc_stago, *wc_tagc;
2166 wc_stago = MakeWideCharString(m_stago);
2167 wc_tagc = MakeWideCharString(m_tagc);
2168 m_err2("Too many characters in BASEFORM for %sTERM%s",
2171 m_free(wc_stago,"wide character string");
2172 m_free(wc_tagc,"wide character string");
2179 if (*p == wnl) *p = wsp;
2184 /* strip possible newlines out of dterm */
2185 for (p = dterm; *p ; p++)
2187 if (*p == wnl) *p = wsp;
2190 /* trim possible last space */
2191 if (termp - dterm > 1 && *(termp-1) == wsp)
2196 idn = (intptr_t) m_lookfortrie(base ? base : dterm, >ree);
2202 m_ntrtrie(base ? base : dterm, >ree, (void *) (intptr_t) idn);
2206 /* Handle the output */
2207 if (vgloss(gloss) == GLOSS)
2210 "<LINK WINDOW=\"%s\" RID=\"%s%d\">",
2214 mb_strcode(buffer, outfile);
2217 mb_strcode("<KEY CLASS=\"TERM\">", outfile);
2220 if (m_mblevel("EXAMPLESEG"))
2222 /* Are we in one of these? May need to number a line. */
2223 for(p = term; *p; p++)
2230 multi_cr_flag = FALSE;
2231 strcode(term, outfile);
2233 mb_strcode("</KEY>", outfile);
2235 if (vgloss(gloss) == GLOSS)
2237 mb_strcode("</LINK>", outfile);
2240 if (echo) mb_echohead("++");
2243 #if defined(M_PROTO)
2244 M_WCHAR wc_toupper(M_WCHAR wc)
2246 M_WCHAR wc_toupper(wc)
2250 if ((wc >= 0) && (wc <= 255))
2252 return _toupper(wc);
2257 #if defined(M_PROTO)
2258 M_WCHAR *wc_stringtoupper(M_WCHAR *wcp)
2260 M_WCHAR *wc_stringtoupper(wcp)
2264 M_WCHAR *newstring, *nsp;
2267 m_malloc(w_strlen(wcp) + 1, "wide character upper case string");
2271 *nsp = wc_toupper(*wcp);
2289 static char *pLang = NULL;
2293 pLang = MakeMByteString(helplang);
2301 static char *pCharset = NULL;
2305 pCharset = MakeMByteString(helpcharset);
2312 #if defined(M_PROTO)
2313 void HandleLink(M_WCHAR *hyperlink, M_WCHAR *type, M_WCHAR *description)
2315 void HandleLink(hyperlink, type, description)
2318 M_WCHAR *description;
2321 char *mb_hyperlink, mb_undefined[64];
2322 char buffer[BIGBUF];
2323 static M_WCHAR wsp = 0;
2327 mbtowc(&wsp, " ", 1);
2330 strcpy(mb_undefined, sdlReservedName);
2331 strcpy(mb_undefined + SDLNAMESIZ - 1, "-UNDEFINED");
2333 mb_strcode("<LINK ", outfile);
2334 global_linktype = 0; /* default to type jump */
2337 /* type is set, choose which is correct */
2338 if (m_wcmbupstrcmp(type, QJUMP))
2339 { /* not type jump */
2340 if (!m_wcmbupstrcmp(type, QJUMPNEWVIEW))
2341 { mb_strcode("WINDOW=\"NEW\" ", outfile); global_linktype = 1;}
2342 else if (!m_wcmbupstrcmp(type, QDEFINITION))
2343 { mb_strcode("WINDOW=\"POPUP\" ", outfile); global_linktype = 2;}
2344 else if (!m_wcmbupstrcmp(type, QEXECUTE))
2345 { global_linktype = 3;}
2346 else if (!m_wcmbupstrcmp(type, QMAN))
2347 { mb_strcode("WINDOW=\"POPUP\" ", outfile); global_linktype = 4;}
2348 else if (!m_wcmbupstrcmp(type, QAPPDEFINED))
2349 { global_linktype = 5;}
2352 mb_strcode("RID=\"", outfile);
2355 mb_hyperlink = MakeMByteString(hyperlink);
2356 if (*mb_hyperlink == '_') /* must be metainfo */
2358 strcpy(buffer, sdlReservedName);
2359 buffer[SDLNAMESIZ-1] = '-';
2360 strcpy(buffer+SDLNAMESIZ, mb_hyperlink+1);
2361 mb_free(&mb_hyperlink);
2368 "Error: %sLINK%s hyperlink was undefined.\n",
2372 "Error: %sLINK%s hyperlink was undefined.\n",
2376 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
2384 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
2391 m_errline("Use ``hyperlink='' if the value contains non-alphabetics");
2393 mb_hyperlink = mb_undefined;
2396 if ((global_linktype <= 2) && hyperlink && (!w_strchr(hyperlink, wsp)))
2399 sprintf(buffer, "%s", mb_hyperlink);
2403 char tmpsnb[BIGBUF];
2406 int nextId = NextId();
2407 sprintf(buffer, "%s%d", sdlReservedName, nextId);
2408 if (!savesnb && snbstart)
2410 fprintf(snbfp, "%d\n", snbstart);
2413 switch (global_linktype)
2416 case 1: /* jump new */
2417 case 2: /* definition */
2419 "<CROSSDOC ID=\"%s%d\" XID",
2423 case 3: /* execute */
2425 "<SYS-CMD ID=\"%s%d\" COMMAND",
2431 "<MAN-PAGE ID=\"%s%d\" XID",
2435 case 5: /* app defined */
2437 "<CALLBACK ID=\"%s%d\" DATA",
2444 snblen = strlen(savesnb);
2445 savesnb = mb_realloc(savesnb, snblen + strlen(tmpsnb) + 1);
2446 strcpy(savesnb + snblen, tmpsnb);
2447 sprintf(tmpsnb, "=\"%s\">\n", mb_hyperlink);
2448 snblen = strlen(savesnb);
2449 savesnb = mb_realloc(savesnb, snblen + strlen(tmpsnb) + 1);
2450 strcpy(savesnb + snblen, tmpsnb);
2454 fputs(tmpsnb, snbfp);
2455 fprintf(snbfp, "=\"%s\">\n", mb_hyperlink);
2458 mb_strcode(buffer, outfile);
2459 mb_strcode("\"", outfile);
2460 if (mb_hyperlink && (mb_hyperlink != mb_undefined))
2461 m_free(mb_hyperlink,"multi-byte string");
2464 char *mb_description;
2466 mb_description = MakeMByteString(description);
2467 sprintf(buffer, " DESCRIPT=\"%s\"", mb_description);
2468 mb_strcode(buffer, outfile);
2469 m_free(mb_description,"multi-byte string");
2471 mb_strcode(">", outfile);
2475 #if defined(M_PROTO)
2476 char *mb_realloc(char *ptr, long size)
2478 char *mb_realloc(ptr, size)
2486 ssize = (size_t) size;
2487 vptr = realloc((void *) ptr, ssize);
2492 fprintf(stdout, "realloc 0x%p 0x%p\n", ptr, vptr);
2497 return (char *) vptr;
2501 #if defined(M_PROTO)
2502 char *mb_malloc(long size)
2504 char *mb_malloc(size)
2511 ssize = (size_t) size;
2512 cptr = (char *) malloc(ssize);
2515 fprintf(stdout, "malloc 0x%p\n", cptr);
2524 #if defined(M_PROTO)
2525 void mb_free(char **pptr)
2533 fprintf(stdout, "free 0x%p\n", *pptr);
2537 free((void *) *pptr);
2541 #if defined(M_PROTO)
2542 static void AddToRowVec(int *length, char **rowvec, char *id)
2544 static void AddToRowVec(length, rowvec, id)
2550 char tempRowVec[BIGBUF];
2553 sprintf(tempRowVec, "<FROWVEC CELLS=\"%s\">\n", id);
2554 rowVecLen = strlen(tempRowVec);
2555 *rowvec = mb_realloc(*rowvec, *length + rowVecLen);
2556 strcpy(*rowvec + *length - 1, tempRowVec);
2557 *length += rowVecLen;
2561 #if defined(M_PROTO)
2562 void Add2ToRowVec(int *length, char **rowvec, char *id1, char *id2)
2564 void Add2ToRowVec(length, rowvec, id1, id2)
2570 char tempRowVec[BIGBUF];
2573 sprintf(tempRowVec, "<FROWVEC CELLS=\"%s %s\">\n", id1, id2);
2574 rowVecLen = strlen(tempRowVec);
2575 *rowvec = mb_realloc(*rowvec, *length + rowVecLen);
2576 strcpy(*rowvec + *length - 1, tempRowVec);
2577 *length += rowVecLen;
2581 #if defined(M_PROTO)
2582 void StartEx(M_WCHAR *notes, M_WCHAR *lines, M_WCHAR *textsize)
2584 void StartEx(*notes, *lines, *textsize)
2590 exTextSize = vextextsize(textsize);
2591 stackex = vstack(notes);
2593 StartBlock(NULL, "EX", NULL);
2595 tonumexlines = (LOGICAL) (vnumber(lines) == NUMBER);
2599 saveex = mb_malloc(1);
2604 #if defined(M_PROTO)
2613 char buffer[BIGBUF];
2618 if (exTextSize == SMALLEST)
2620 else if (exTextSize == SMALLER)
2624 length = sprintf(buffer, "<P TYPE=\"LITERAL\" SSI=\"EX-%s\">", ssi);
2628 length += sprintf(buffer + length,
2629 "<HEAD TYPE=\"LINED\" SSI=\"EX-NUM\">");
2630 while (oldExLineNum <= exLineNum)
2632 length += sprintf(buffer + length, "%2d:\n", oldExLineNum);
2635 length += sprintf(buffer + length, "</HEAD>");
2640 annotation = MakeMByteString(savehead);
2641 annotLen = strlen(annotation);
2648 saveex = mb_realloc(saveex,
2649 svexlen + length + (svexseglen - 1) + annotLen + 5);
2651 strcpy(saveex + svexlen - 1, buffer);
2656 strcpy(saveex + svexlen - 1, annotation);
2657 svexlen += annotLen;
2660 strcpy(saveex + svexlen - 1, saveexseg);
2661 svexlen += svexseglen - 1;
2663 strcpy(saveex + svexlen - 1, "</P>\n");
2665 mb_free(&saveexseg);
2668 m_free(annotation, "multi-byte string");
2673 #if defined(M_PROTO)
2674 void StartNCW(char *which)
2676 void StartNCW(which)
2681 PushForm(NULL, which, NULL);
2685 #if defined(M_PROTO)
2686 void StartBlock(char *pclass, char *ssi, char *id)
2688 void StartBlock(pclass, ssi, id)
2689 char *pclass, *ssi, *id;
2697 fputs("<FDATA>\n", outfile);
2702 fputs("</BLOCK>\n", outfile);
2705 if (formStackBase && (formStackTop >= formStackBase))
2706 { /* there is a <form> in progress */
2709 sprintf(localId, "%s%d", sdlReservedName, NextId());
2712 AddToRowVec(&(formStackTop->vecLen), &(formStackTop->rowVec), realId);
2715 fputs("<BLOCK", outfile);
2717 fprintf(outfile, " ID=\"%s\"", realId);
2719 fprintf(outfile, " CLASS=\"%s\"", pclass);
2721 fprintf(outfile, " SSI=\"%s\"", ssi);
2722 fputs(">\n", outfile);
2725 firstPInBlock = TRUE;
2729 #if defined(M_PROTO)
2730 void StartNCWtext(char *which, char *iconFile, char *headingString)
2732 void StartNCWtext(which, iconFile, headingString)
2735 char *headingString;
2738 char *icon, *heading;
2740 /* Write default head if no user-specified head was encountered */
2743 heading = GetDefaultHeaderString(headingString, M_SDATA, which);
2744 fprintf(outfile, "<HEAD SSI=\"NCW\">%s", heading);
2745 fputs("</HEAD>\n", outfile);
2747 m_free(heading, "default header string return");
2750 icon = GetDefaultHeaderString(iconFile, M_SYSTEM, "");
2755 sprintf(id, "%s%d", sdlReservedName, NextId());
2757 "<HEAD SSI=\"NCW-ICON\"><SNREF>\n<REFITEM RID=\"%s\" ",
2759 fputs("CLASS=\"ICON\" SSI=\"NCW-ICON\">", outfile);
2760 fputs("</REFITEM>\n</SNREF></HEAD>\n", outfile);
2763 m_free(icon, "icon name");
2767 #if defined(M_PROTO)
2768 void AddToSNB(char *id, char *xid)
2770 void AddToSNB(id, xid)
2775 char tmpsnb[BIGBUF];
2780 sprintf(tmpsnb, "<GRAPHIC ID=\"%s\" XID=\"%s\">\n", id, xid);
2781 snblen = strlen(savesnb);
2782 savesnb = mb_realloc(savesnb, snblen + strlen(tmpsnb) + 1);
2783 strcpy(savesnb + snblen, tmpsnb);
2789 fprintf(snbfp, "%d\n", snbstart);
2792 fprintf(snbfp, "<GRAPHIC ID=\"%s\" XID=\"%s\">\n", id, xid);
2797 #if defined(M_PROTO)
2803 char pathbuf[BIGBUF];
2804 char *try = pathbuf;
2805 int tryleng = sizeof(pathbuf);
2810 M_WCHAR *wc_try, *wc_outputname;
2812 char filebuf[BIGBUF];
2814 char **tossline = toss;
2816 /* the code below assume the extensions are .htg, .tss and .sdl */
2817 /* or at least that all extensions are 3 character plus a dot */
2819 fileleng = w_strlen(inputname);
2820 mb_inputname = mb_malloc(fileleng + 1);
2821 wcstombs(mb_inputname, inputname, fileleng);
2822 strcpy(mb_inputname + fileleng - 4, ".tss");
2828 pathleng = strlen(thispath->directory);
2829 if ((pathleng + fileleng) >= tryleng)
2831 tryleng = pathleng + fileleng + 1;
2833 try = mb_malloc(tryleng);
2835 try = mb_realloc(try, tryleng);
2837 strcpy(try, thispath->directory);
2838 strcpy(try + pathleng, mb_inputname);
2839 tossfile = open(try, O_RDONLY);
2840 if (tossfile >= 0) break;
2841 thispath = thispath->next;
2846 fputs("<TOSS>\n", outfile);
2847 while ((bytesread = read(tossfile, filebuf, sizeof(filebuf))) > 0)
2851 outfile) != bytesread) break;
2854 strcpy(mb_inputname + fileleng - 4, ".sdl");
2855 wc_outputname = MakeWideCharString(mb_inputname);
2856 wc_try = MakeWideCharString(try);
2857 m_err2("error copying %s to output (%s) as the <toss> element",
2860 m_free(wc_try, "wide character toss input name");
2861 m_free(wc_outputname, "wide character output name");
2864 fputs("</TOSS>\n", outfile);
2870 fputs(*tossline++, outfile);
2871 fputs("\n", outfile);
2875 if (try != pathbuf) mb_free(&try);
2876 mb_free(&mb_inputname);
2879 /* Below is a modified version of m_cyclent() that returns a pointer
2880 * to the entity content rather than its value. Returning a pointer
2881 * to the entity's content field allows it to be modified.
2883 /* Cyclent.c contains procedure m_cyclent(), callable by interface
2884 designers, to cycle through all defined entities, returning information
2886 #if defined(M_PROTO)
2887 M_WCHAR *CycleEnt(LOGICAL init,
2888 unsigned char *type,
2890 unsigned char *wheredef)
2892 M_WCHAR *m_cyclent(init, type, content, wheredef)
2894 unsigned char *type ;
2895 M_WCHAR ***content ;
2896 unsigned char *wheredef ;
2899 static M_TRIE *current ;
2900 static M_TRIE *ancestor[M_NAMELEN + 1] ;
2902 static M_WCHAR name[M_NAMELEN + 1] ;
2906 current = m_enttrie->data ;
2910 if (length < 0) return(NULL) ;
2912 while (current->symbol)
2914 ancestor[length] = current ;
2915 name[length++] = current->symbol ;
2916 current = current->data ;
2918 name[length] = M_EOS ;
2920 *type = ((M_ENTITY *) current->data)->type ;
2921 *content = &(((M_ENTITY *) current->data)->content) ;
2922 *wheredef = ((M_ENTITY *) current->data)->wheredef ;
2928 current = current->next ;
2932 if (length < 0) break ;
2933 current = ancestor[length] ;
2939 /* A routine to examine all defined entities looking for ones of type
2940 * M_SDATA. When found, if the entity's content is of the form
2941 * [......] (six characters surrounded by square brackets), its
2942 * content is modified to be <SPC NAME="[......]"> so that it may be
2943 * emitted into the SDL output.
2945 void ModifyEntities()
2948 unsigned char wheredef;
2952 M_WCHAR *newContent;
2953 static char mb_newContent[] = "<SPC NAME=\"[123456]\">";
2955 name = CycleEnt(TRUE, &type, &content, &wheredef);
2958 mb_newContent[21] = '\0';
2961 if ((type == M_SDATA) && *content)
2963 mb_content = MakeMByteString(*content);
2964 if ((strlen(mb_content) == 8) &&
2965 (mb_content[0] == '[') &&
2966 (mb_content[7] == ']'))
2968 strncpy(mb_newContent+11, mb_content, 8);
2969 if (wheredef == M_DPARSER)
2970 m_free(*content, "old SDATA entity content");
2971 *content = MakeWideCharString(mb_newContent);
2973 m_free(mb_content, "multi-byte SDATA entity content");
2976 while (name = CycleEnt(FALSE, &type, &content, &wheredef));
2980 #if defined(M_PROTO)
2981 void PushForm(char *class, char *ssi, char *id)
2983 void PushForm(class, ssi, id)
2989 char localId[SDLNAMESIZ+10];
2995 fputs("<FDATA>\n", outfile);
3001 fputs("</BLOCK>\n", outfile);
3006 if (formStackBase && (formStackTop >= formStackBase))
3007 { /* there is a <form> in progress */
3010 sprintf(localId, "%s%d", sdlReservedName, NextId());
3013 AddToRowVec(&(formStackTop->vecLen), &(formStackTop->rowVec), realId);
3016 if (formStackTop == formStackMax)
3020 formStackBase = (FORMINFO *) malloc(10 * sizeof(FORMINFO));
3021 formStackTop = formStackBase;
3022 formStackMax = formStackBase + 9;
3026 stackSize = formStackMax - formStackBase + 1;
3028 realloc(formStackBase, (stackSize + 10) * sizeof(FORMINFO));
3029 formStackTop = formStackBase + stackSize;
3030 formStackMax = formStackBase + (stackSize + 9);
3036 formStackTop->rowVec = mb_malloc(1);
3037 formStackTop->vecLen = 1;
3039 fputs("<FORM", outfile);
3041 fprintf(outfile, " ID=\"%s\"", realId);
3043 fprintf(outfile, " CLASS=\"%s\"", class);
3045 fprintf(outfile, " SSI=\"%s\"", ssi);
3046 fputs(">\n", outfile);
3051 #if defined(M_PROTO)
3052 void PushForm2(char *class, char *ssi, char *id1, char *id2)
3054 void PushForm2(class, ssi, id1, id2)
3067 fputs("<FDATA>\n", outfile);
3073 fputs("</BLOCK>\n", outfile);
3079 sprintf(id, "%s%d", sdlReservedName, formId = NextId());
3083 if (formStackBase && (formStackTop >= formStackBase))
3084 { /* there is a <form> in progress */
3085 Add2ToRowVec(&(formStackTop->vecLen),
3086 &(formStackTop->rowVec),
3091 if (formStackTop == formStackMax)
3095 formStackBase = (FORMINFO *) malloc(10 * sizeof(FORMINFO));
3096 formStackTop = formStackBase;
3097 formStackMax = formStackBase + 9;
3101 stackSize = formStackMax - formStackBase + 1;
3103 realloc(formStackBase, (stackSize + 10) * sizeof(FORMINFO));
3104 formStackTop = formStackBase + stackSize;
3105 formStackMax = formStackBase + (stackSize + 9);
3111 formStackTop->rowVec = mb_malloc(1);
3112 formStackTop->vecLen = 1;
3114 fprintf(outfile, "<FORM ID=\"%s\"", id2);
3116 fprintf(outfile, " CLASS=\"%s\"", class);
3118 fprintf(outfile, " SSI=\"%s\"", ssi);
3119 fputs(">\n", outfile);
3127 fputs("</BLOCK>\n", outfile);
3132 "</FDATA>\n<FSTYLE>\n%s</FSTYLE>\n</FORM>\n",
3133 formStackTop->rowVec);
3135 mb_free(&(formStackTop->rowVec));
3143 fputs("</BLOCK>\n", outfile);
3148 "</FDATA>\n<FSTYLE NCOLS=\"2\">\n%s</FSTYLE>\n</FORM>\n",
3149 formStackTop->rowVec);
3151 mb_free(&(formStackTop->rowVec));
3155 /* look to see if there's an open form with no data; if so, add a data
3156 * block and close the form. This situation will happen when a form
3157 * is pushed but the source doesn't go to text either because the text
3158 * is explicitly optional or due to the fact that text can be null.
3162 if ((formStackTop >= formStackBase) && (formStackTop->vecLen == 1))
3164 StartBlock(NULL, NULL, NULL);
3169 void EmitSavedAnchors()
3171 char buffer[BIGBUF];
3176 "<ANCHOR ID=\"%s%d\">",
3179 mb_strcode(buffer, outfile);
3188 fputs("<BLOCK>\n<P>", outfile);
3190 fputs("</P>\n</BLOCK>", outfile);
3192 fputs("</VIRPAGE>\n", outfile);