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 librararies 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 strcpy(patbuf, 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 strcpy(orderString, ROMAN100[count / 100]);
826 strcat(orderString, ROMAN10[(count / 10) % 10]);
827 strcat(orderString, ROMAN0[count % 10]);
832 while ((count -= 26) > 0) metaCount++;
833 count = lastlist->lastlist->count;
834 if (count > 999) count = 999;
837 while (--metaCount >= 0) strncat(orderString, &ALPHABET[count], 1);
841 if (metaCount = (count / 100))
842 strncat(orderString, &numbers[metaCount], 1);
843 if (metaCount || ((count / 10) % 10))
844 strncat(orderString, &numbers[(count / 10) % 10], 1);
845 strncat(orderString, &numbers[count % 10], 1);
849 strcpy(orderString, roman100[count / 100]);
850 strcat(orderString, roman10[(count / 10) % 10]);
851 strcat(orderString, roman0[count % 10]);
856 while ((count -= 26) > 0) metaCount++;
857 count = lastlist->lastlist->count;
858 if (count > 999) count = 999;
861 while (--metaCount >= 0) strncat(orderString, &alphabet[count], 1);
866 "%s%s-%s\">\n<P>%s%c",
871 lastlist->lastlist->punct == DOTPUNCT ? '.' : ')' );
877 sprintf(buffer, "Item %s", orderString);
878 wc = MakeWideCharString(buffer);
879 w_strcpy(xrefstring, wc);
880 m_free(wc,"wide character string");
882 xstrlen = w_strlen(xrefstring);
883 m_getline(&xrffile, &xrfline);
886 /* set to primary input */
898 item_id = MakeMByteString(id);
902 { /* Bullet, Check or Plain list */
903 if (id) m_error("Cross-reference ID in non-ORDER list not allowed");
904 /* already handled Bullet */
905 if (listtype == CHECK)
908 "%s%s-CHECK\">\n<P><SPC NAME=\"[check ]\">",
912 /* don't emit label for listtype==PLAIN and listtype==MILSPEC */
915 if ((listtype != PLAIN) && (listtype != MILSPEC) && (listtype != BULLET))
916 fputs("</P>\n</BLOCK>\n", outfile);
918 sprintf(ssi, "%s%s", first, loose);
919 if ((listtype == PLAIN) || (listtype == MILSPEC))
920 PushForm("ITEM", ssi, item_id);
922 PushForm2("ITEM", ssi, label_id, item_id);
925 m_free(item_id, "multi-byte string");
937 } /* END procedure rsectstart */
940 /* Called at the end of a chapter, appendix, or section to end an open
941 sequence of rsects */
942 void rseqend(M_NOPAR)
950 /* Follow search path to find a file, returning qualified name */
951 M_WCHAR *searchforfile(file)
956 char *mb_file, mb_filename[2048];
957 int dir_leng,file_leng;
959 mb_file = MakeMByteString(file);
960 if (! access(mb_file, READABLE))
962 filename = (M_WCHAR *)
963 m_malloc(w_strlen(file) + 1, "figure/icon filename");
964 w_strcpy(filename, file);
965 m_free(mb_file,"multi-byte string");
969 file_leng = strlen(mb_file);
970 for (searchp = path; searchp ; searchp = searchp->next)
972 if (((dir_leng = strlen(searchp->directory)) + file_leng) >= 2048)
976 wc = MakeWideCharString(searchp->directory);
977 m_err2("%s and %s overflow the file name space", wc, file);
978 m_free(wc,"wide character string");
981 strcpy(mb_filename, searchp->directory);
982 strcpy(mb_filename+dir_leng, mb_file);
983 if (! access(mb_filename, READABLE))
985 m_free(mb_file,"multi-byte string");
986 return(MakeWideCharString(mb_filename));
990 m_free(mb_file,"multi-byte string");
995 /* Start a new helpnode */
997 void starthelpnode(M_WCHAR *ssi,
1001 void starthelpnode(ssi, id, level)
1008 char *mbyte, *mb_ssi;
1009 char mb_nodeid[NODEID_LENGTH+1], nodenum[32];
1011 if (outfile != m_outfile)
1013 m_error("Internal warning: Outfile has been redirected.");
1019 mb_ssi = MakeMByteString(ssi);
1021 /* we can't use the bullet block across virpage boundaries */
1024 looseBulletId[0] = 0;
1025 looseBulletId[1] = 0;
1027 firstLooseBulletId = 0;
1029 /* might as well always start with id 0 (we flip first) */
1031 looseBulletIdIndex = 1;
1033 if ((id == NULL) || (*id == 0))
1035 strcpy(mb_nodeid, sdlReservedName);
1036 m_itoa(NextId(), nodenum);
1037 strcpy(mb_nodeid + SDLNAMESIZ - 1, nodenum);
1038 mbstowcs(nodeid, mb_nodeid, NODEID_LENGTH);
1042 w_strncpy(nodeid, id, NODEID_LENGTH);
1043 wcstombs(mb_nodeid, id, NODEID_LENGTH);
1047 "<VIRPAGE ID=\"%s\" LEVEL=\"%d\" LANGUAGE=\"%s\" CHARSET=\"%s\" DOC-ID=\"%s\" SSI=\"%s\">\n",
1054 m_free(mb_ssi,"multi-byte string");
1055 snbstart = ftell(outfile);
1056 } /* End starthelpnode(id) */
1059 #if defined(M_PROTO)
1060 void mb_starthelpnode(char *ssi,
1064 void mb_starthelpnode(ssi, id, level)
1070 M_WCHAR *wc_ssi, *wc_id;
1074 wc_ssi = MakeWideCharString(ssi);
1077 wc_id = MakeWideCharString(id);
1078 starthelpnode(wc_ssi, wc_id, level);
1080 m_free(wc_ssi,"wide character string");
1082 m_free(wc_id,"wide character string");
1086 /* Start a labeled list */
1087 void StartLabList(spacing, longlabel)
1092 static char def_spacing[] = "LOOSE";
1095 if (list >= MAXLISTLEV)
1096 m_error("Nesting of <LIST> and <LABLIST> too deep");
1099 mb_spacing = MakeMByteString(spacing);
1101 mb_spacing = def_spacing;
1103 sprintf(ssi, "LABELED-%s", mb_spacing);
1104 PushForm("LIST", ssi, NULL);
1106 if (mb_spacing != def_spacing)
1107 mb_free(&mb_spacing);
1111 listitems[list].firstitem = TRUE;
1112 listitems[list].longlabel = vlonglabel(longlabel);
1114 if (list <= MAXLISTLEV)
1116 if (vspacing(spacing) == TIGHT)
1118 lablisttight[list] = TRUE;
1122 lablisttight[list] = FALSE;
1129 #if defined(M_PROTO)
1130 void StartList(M_WCHAR *type,
1135 void StartList(type, order, spacing, cont)
1136 M_WCHAR *type, *order, *spacing, *cont;
1144 static char def_spacing[] = "LOOSE";
1150 mb_spacing = MakeMByteString(spacing);
1154 mb_spacing = def_spacing;
1159 if (list > MAXLISTLEV)
1160 m_error("Nesting of <LIST> and <LABLIST> too deep");
1162 if (! lastlist->started && cont)
1164 m_error("No previous list to continue");
1170 if (order && (vordertype(order) != lastlist->order))
1172 m_error("Unable to continue a list and change the numbering scheme");
1176 if (type && (vtype(type) != lastlist->type))
1178 m_error("Unable to continue a list and change its type");
1184 { /* clear old list? */
1185 for (chain = lastlist->chain; chain ; chain = xchain)
1187 xchain = chain->next;
1188 m_free(chain, "list chain");
1190 lastlist->chain = NULL;
1191 lastlist->count = 0;
1194 /* If outermost list, initialize according to current defaults */
1195 if (! cont && lastlist == &outlist)
1197 outlist.type = vtype(NULL);
1198 outlist.order = vordertype(NULL);
1200 outlist.space = vspacing(NULL);
1201 outlist.punct = DOTPUNCT;
1204 if (type) lastlist->type = vtype(type);
1208 lastlist->type = ORDER;
1209 lastlist->order = vordertype(order);
1212 switch (lastlist->type)
1216 list_type = "PLAIN";
1219 list_type = "CHECK";
1222 list_type = "ORDER";
1226 list_type = "BULLET";
1228 sprintf(ssi, "%s-%s", list_type, mb_spacing);
1230 PushForm("LIST", ssi, NULL);
1232 if (mb_spacing != def_spacing)
1233 m_free(mb_spacing, "multi-byte string");
1236 lastlist->space = LOOSE;
1237 if (spacing && ! m_wcmbupstrcmp(spacing, QTIGHT)) lastlist->space = TIGHT;
1239 if (type && order && m_wcmbupstrcmp(type, QORDER))
1240 m_err2("Incompatible specification for list: %s and %s", type, order);
1242 if (lastlist->type == ORDER)
1244 chain = (CONTCHAIN *) m_malloc(sizeof(CONTCHAIN), "list chain");
1245 chain->next = lastlist->chain;
1246 lastlist->chain = chain;
1247 chain->where = ftell(outfile);
1250 lastlist->started = TRUE;
1251 listitems[list].firstitem = TRUE;
1253 /* Prepare for sublist */
1254 nextlist = (LIST *) m_malloc(sizeof(LIST), "list structure");
1255 nextlist->lastlist = lastlist;
1256 nextlist->type = lastlist->type;
1257 nextlist->punct = lastlist->punct;
1258 if (lastlist->type == ORDER)
1260 nextlist->order = lastlist->order + 1;
1261 if (nextlist->order > LROMAN)
1263 nextlist->order = ARABIC;
1264 nextlist->punct = PARENPUNCT;
1267 else nextlist->order = lastlist->order;
1268 nextlist->count = 0;
1269 nextlist->space = lastlist->space;
1270 nextlist->started = FALSE;
1271 nextlist->where = FIRST;
1272 nextlist->chain = NULL;
1273 lastlist = nextlist;
1280 CONTCHAIN *chain, *xchain ;
1283 curlist = lastlist->lastlist ;
1285 if ((curlist->type == PLAIN) || (curlist->type == MILSPEC))
1292 for (chain = lastlist->chain ; chain ; chain = xchain)
1294 xchain = chain->next ;
1295 m_free(chain, "list chain") ;
1297 m_free(lastlist, "list structure") ;
1298 lastlist = curlist ;
1299 for (chain = lastlist->chain ; chain ; chain = chain->next)
1301 if (lastlist->count > 999)
1303 m_error("Unable to support more than 999 items in an ordered list") ;
1304 lastlist->count = 999 ;
1307 if (lastlist->type == BULLET) bulcount-- ;
1311 /* Open and initialize TeX file */
1312 void texinit(M_NOPAR)
1314 LOGICAL init = TRUE;
1317 unsigned char wheredef;
1328 /* Check .XRF file */
1329 strcpy(helpext, ".xrh");
1330 xrf = fopen(helpbase, "r");
1331 if (! xrf) rebuild = TRUE;
1334 fscanf(xrf, "\\gobble\001");
1335 for (p = m_signon; *p ; p++)
1341 "Output files from different version of Tag, regenerating. . .\n");
1350 while ((ic = getc(xrf)) != EOF)
1351 if (ic == '\n') break;
1352 if (xrf && ic !=EOF)
1353 while ((ic = getc(xrf)) != EOF)
1354 if (ic == '\n') break;
1358 /* Open output files */
1359 strcpy(helpext, ".sdl");
1360 m_openchk(&m_outfile, helpbase, "w");
1361 outfile = m_outfile;
1363 savehelpfilename = (M_WCHAR *)m_malloc(strlen(helpbase)+1, "help file name");
1364 mbstowcs(savehelpfilename, helpbase, strlen(helpbase) + 1);
1367 strcpy(helpext, ".idx");
1368 m_openchk(&indexfp, helpbase, "wb");
1370 /* system notation block file */
1371 strcpy(helpext, ".snb");
1372 m_openchk(&snbfp, helpbase, "wb");
1374 while (name = m_cyclent(init, &type, &content, &wheredef))
1380 if (type == M_SYSTEM)
1381 qfile = searchforfile(content);
1383 if (qfile) m_free(qfile, "figure filename");
1385 if (type == M_SYSTEM)
1387 mbtowc(&wsl, "/", 1);
1389 if (w_strchr(content, wsl))
1391 m_err2("Avoid directory names in FILE entity %s: %s",
1394 m_errline("(Use the SEARCH option instead)\n");
1399 /* Include cross-reference file */
1400 strcpy(helpext, ".xrh");
1402 postpreamble = ftell(outfile);
1406 /* Lookup localized header string entity as defined (by default) in
1407 locallang.ent. If the the header string was not found, or it was
1408 not of type "desiredType", return the default.
1410 If the entity is of type file (M_SYSTEM) then if the content is not
1411 empty search the path for the file. If the file is found, return
1412 its name else return an empty string.
1414 If this routine returns anything other than the empty string (""),
1415 the string returned must be m_free'd.
1418 #if defined(M_PROTO)
1419 GetDefaultHeaderString(
1421 unsigned char desiredType,
1422 char *defaultString )
1424 GetDefaultHeaderString(elementName, desiredType, defaultString)
1426 unsigned char desiredType;
1427 char *defaultString;
1430 unsigned char type,wheredef;
1433 M_WCHAR *wc_elementName;
1437 wc_elementName = MakeWideCharString(elementName);
1438 if (m_lookent(wc_elementName, &type, &content, &wheredef))
1440 if (type == desiredType)
1442 if (type == M_SDATA)
1444 m_free(wc_elementName,"wide character string");
1445 mb_content = MakeMByteString(content);
1448 m_free(mb_content,"multi-byte string");
1456 path = searchforfile(content);
1459 m_err2("Can't find file %s (declared in entity %s)",
1462 m_free(wc_elementName,"wide character string");
1467 m_free(wc_elementName,"wide character string");
1468 return MakeMByteString(path);
1471 m_free(wc_elementName,"wide character string");
1476 m_free(wc_elementName,"wide character string");
1479 retval = m_malloc(strlen(defaultString) + 1,
1480 "GetDefaultHeaderString return");
1481 return strcpy(retval, defaultString);
1488 /* A function that takes a language/charset pair and:
1489 * if they are standard, leave them unchanged but get local
1490 * versions and setlocale(3) using those
1491 * if they are local, setlocale(3) with them and replace them with
1492 * standard versions.
1495 #if defined(M_PROTO)
1496 SetStdLocale(char *pLang, char *pCharset)
1498 SetStdLocale(pLang, pCharset)
1503 static const char *cString = "C";
1504 static const char *isoString = "ISO-8859-1";
1505 _DtXlateDb myDb = NULL;
1506 char myPlatform[_DtPLATFORM_MAX_LEN+1];
1507 char myLocale[256]; /* arbitrarily large */
1515 strcpy(myLocale, pLang);
1518 strcat(myLocale, ".");
1519 strcat(myLocale, pCharset);
1522 if ((_DtLcxOpenAllDbs(&myDb) != 0) ||
1523 (_DtXlateGetXlateEnv(myDb,myPlatform,&execVer,&compVer) != 0))
1526 "Warning: could not open locale translation database.\n");
1527 if (m_errfile != stderr)
1529 "Warning: could not open locale translation database.\n");
1530 strcpy(pLang, cString);
1531 strcpy(pCharset, isoString);
1533 _DtLcxCloseDb(&myDb);
1537 isStd = !_DtLcxXlateOpToStd(myDb,
1548 { /* already standard - get local versions and set locale */
1549 if (_DtLcxXlateStdToOp(myDb,
1552 DtLCX_OPER_SETLOCALE,
1560 "Warning: could not translate CDE locale to local\n");
1561 if (m_errfile != stderr)
1563 "Warning: could not translate CDE locale to local\n");
1564 strcpy(pLang, cString);
1565 strcpy(pCharset, isoString);
1566 _DtLcxCloseDb(&myDb);
1571 setlocale(LC_CTYPE, locale);
1576 { /* already local - set locale and get standard versions */
1577 if (_DtLcxXlateOpToStd(myDb,
1580 DtLCX_OPER_SETLOCALE,
1588 "Warning: could not translate local locale to CDE\n");
1589 if (m_errfile != stderr)
1591 "Warning: could not translate local locale to CDE\n");
1592 strcpy(pLang, cString);
1593 strcpy(pCharset, isoString);
1594 _DtLcxCloseDb(&myDb);
1597 setlocale(LC_CTYPE, myLocale);
1601 strcpy(pLang, lang);
1605 strcpy(pLang, cString);
1609 strcpy(pCharset, charset);
1613 strcpy(pCharset, isoString);
1616 _DtLcxCloseDb(&myDb);
1622 /* A function that takes the return value from a call to setlocale()
1623 * and extracts the langterr.charset data from it in a vendor neutral
1627 #if defined(M_PROTO)
1633 static char buffer[256];
1634 static char *cString = "C";
1635 _DtXlateDb myDb = NULL;
1636 char myPlatform[_DtPLATFORM_MAX_LEN+1];
1642 if ((_DtLcxOpenAllDbs(&myDb) == 0) &&
1643 (_DtXlateGetXlateEnv(myDb,myPlatform,&execVer,&compVer) != 0))
1646 "Warning: could not open locale translation database.\n");
1647 if (m_errfile != stderr)
1649 "Warning: could not open locale translation database.\n");
1653 if (_DtLcxXlateOpToStd(myDb,
1656 DtLCX_OPER_SETLOCALE,
1657 setlocale(LC_ALL, NULL),
1664 "Warning: could not translate local locale to CDE\n");
1665 if (m_errfile != stderr)
1667 "Warning: could not translate local locale to CDE\n");
1668 _DtLcxCloseDb(&myDb);
1672 if (_DtLcxXlateStdToOp(myDb,
1675 DtLCX_OPER_SETLOCALE,
1683 "Warning: could not translate CDE locale to local\n");
1684 if (m_errfile != stderr)
1686 "Warning: could not translate CDE locale to local\n");
1687 mb_free(&stdLocale);
1688 _DtLcxCloseDb(&myDb);
1692 _DtLcxCloseDb(&myDb);
1694 strcpy(buffer, opLocale);
1695 mb_free(&stdLocale);
1702 * Look for a entities by the name of "LanguageElementDefaultLocale".
1703 * and "LanguageElementDefaultCharset". If not found, get the user's
1704 * locale. If LanguageElementDefaultCharset was set, use that in
1705 * place of the charset of the local (if any). Call SetStdLocale()
1706 * to insure the language and charset are in the normalized form.
1707 * SetStdLocale() will also set the current locale to the local
1708 * versions of the language and charset.
1713 unsigned char type,wheredef;
1714 M_WCHAR *elementName;
1720 char stdLang[256]; /* arbitrarily large */
1721 char stdCharset[256]; /* arbitrarily large */
1729 elementName = MakeWideCharString("LanguageElementDefaultLocale");
1730 if (m_lookent(elementName, &type, &content, &wheredef))
1732 if (type == M_SDATA)
1734 locale = MakeMByteString(content);
1737 m_free(elementName,"wide character string");
1741 tmpStr = GetStdLocale();
1742 locale = mb_malloc(strlen(tmpStr)+1);
1743 strcpy(locale, tmpStr);
1746 dotPtr = strchr(locale, '.');
1750 charset = MakeMByteString(helpcharset);
1751 m_free(helpcharset, "help charset");
1756 elementName = MakeWideCharString("LanguageElementDefaultCharset");
1757 if (m_lookent(elementName, &type, &content, &wheredef))
1759 if (type == M_SDATA)
1761 charset = MakeMByteString(content);
1764 m_free(elementName,"wide character string");
1770 charset = dotPtr + 1;
1775 strcpy(stdLang, locale);
1777 strcpy(stdCharset, charset);
1778 SetStdLocale(stdLang, stdCharset);
1781 helpcharset = MakeWideCharString(stdCharset);
1782 helplang = MakeWideCharString(stdLang);
1785 if (charset && (charset != (dotPtr+1)))
1790 #if defined(M_PROTO)
1791 void paragraph(M_WCHAR *indent,
1795 M_WCHAR *ghyperlink,
1797 M_WCHAR *gdescription)
1799 void paragraph(indent,
1810 M_WCHAR *ghyperlink;
1812 M_WCHAR *gdescription;
1815 char *firstString, *indentString;
1819 savid = checkid(id);
1824 StartBlock(NULL, NULL, NULL);
1825 fputs("<P", outfile);
1830 mb_id = MakeMByteString(id);
1831 fprintf(outfile, " ID=\"%s\"", mb_id);
1832 m_free(mb_id,"multi-byte string");
1839 firstPInBlock = FALSE;
1844 indentString = "-INDENT";
1846 fprintf(outfile, " SSI=\"P%s%s\">", firstString, indentString);
1848 handle_link_and_graphic(m_parent(0),
1857 #if defined(M_PROTO)
1865 M_WCHAR *ghyperlink,
1867 M_WCHAR *gdescription)
1886 M_WCHAR *ghyperlink;
1888 M_WCHAR *gdescription;
1892 unsigned char etype,wheredef;
1894 GetDefaultHeaderString("FigureElementDefaultHeadingString",
1900 fputs("<FDATA>\n", outfile);
1904 StartBlock(NULL, NULL, NULL);
1907 fputs("<P SSI=\"FIGURE\">\n", outfile);
1911 HandleLink(ghyperlink, glinktype, gdescription);
1913 else if (glinktype || gdescription)
1917 "Error: %sP%s ghyperlink was undefined.\n",
1921 "Error: %sP%s ghyperlink was undefined.\n",
1925 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
1933 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
1940 m_errline("Use ``ghyperlink='' if the value contains non-alphabetics");
1943 /* end of link specific code */
1946 ftonumber = (!tonumber || (vnumber(tonumber) == NUMBER));
1947 if (id && ! ftonumber)
1949 m_error("Figures with ID's must be numbered");
1952 if (ftonumber) figno++;
1958 mb_number = MakeMByteString(number);
1959 figno = atoi(mb_number);
1960 m_free(mb_number,"multi-byte string");
1962 m_err1("Explicit figure number %s inconsistent with NONUMBER option",
1969 char mb_xrefstring[400];
1971 sprintf(mb_xrefstring, "%s %d", string, figno);
1972 mbstowcs(xrefstring, mb_xrefstring, 400);
1973 xstrlen = w_strlen(xrefstring);
1974 m_getline(&xrffile, &xrfline);
1975 if (xrffile == NULL)
1977 /* set to primary input source */
1978 xrffile = inputname;
1980 setid(id, TRUE, FALSE, inchapter, chapstring, xrffile, xrfline, TRUE);
1983 /* initialize some stuff first:
1984 - file is the entity name,
1985 - f_file is the content of the entity,
1986 used only if f_content nonNULL
1987 - f_content is f_file with the relative pathname, initialized to NULL,
1988 - f_contqual is fully qualified f_file, assigned ONLY IF
1993 f_contqual[0] = M_EOS;
1995 /* check ENTITY and determine the figure type */
1998 m_lookent(file, &etype, &f_file, &wheredef);
1999 if (etype != M_SYSTEM)
2001 M_WCHAR *wc_stago, *wc_tagc;
2002 M_WCHAR *wc_entsystem, *wc_entkw;
2004 wc_stago = MakeWideCharString(m_stago);
2005 wc_tagc = MakeWideCharString(m_tagc);
2006 wc_entsystem = MakeWideCharString(m_entsystem);
2007 wc_entkw = MakeWideCharString(m_entkw);
2008 m_err6("%s not a %s %s, as required for the ENTITY parameter of %s%s%s",
2015 m_free(wc_stago,"wide character string");
2016 m_free(wc_tagc,"wide character string");
2017 m_free(wc_entsystem,"wide character string");
2018 m_free(wc_entkw,"wide character string");
2023 f_content = searchforfile(f_file);
2026 if (getqualified(f_contqual, f_content))
2028 /* unsuccessful qual */
2029 if (w_strlen(f_content) < FNAMELEN)
2030 w_strcpy(f_contqual, f_content);
2033 m_err1("Internal error. File name too long: %s",
2041 m_err2("Can't find file %s (declared in entity %s)",
2048 sprintf(snb_id, "%s%d", sdlReservedName, NextId());
2051 static M_WCHAR empty = M_EOS;
2054 if (!f_content) f_content = ∅
2056 mb_content = MakeMByteString(f_content);
2057 AddToSNB(snb_id, mb_content);
2058 m_free(mb_content,"multi-byte string");
2061 fputs("<SNREF", outfile);
2067 mb_id = MakeMByteString(id);
2068 fprintf(outfile, " ID=\"%s\"", mb_id);
2069 m_free(mb_id,"multi-byte string");
2071 fprintf(outfile, ">\n<REFITEM RID=\"%s\" CLASS=\"FIGURE\" SSI=\"FIG", snb_id);
2074 /* if caption position is not specified, have it track the figure position */
2079 switch (vcenter(figpos))
2082 fputs("-LEFT", outfile);
2085 fputs("-CENTER", outfile);
2088 fputs("-RIGHT", outfile);
2091 fputs("\">\n", outfile);
2095 switch (vcenter(cappos))
2098 capposition = "-LEFT";
2101 capposition = "-CENTER";
2104 capposition = "-RIGHT";
2111 "<HEAD TYPE=\"LINED\" CLASS=\"CAPTION\" SSI=\"NUMBER%s\">%s %d.",
2116 m_free(string, "default header string return");
2119 #if defined(M_PROTO)
2120 void endterm(M_WCHAR *base, M_WCHAR *gloss, char *linktype)
2122 void endterm( base, gloss, linktype)
2129 M_WCHAR dterm[MAXTERM+1];
2131 char buffer[BIGBUF];
2134 if (!(m_mblevel("HEAD") ||
2135 m_mblevel("EXAMPLESEG") ||
2136 m_mblevel("ANNOTATION")
2140 /* Don't re-enable output yet if in a <HEAD>, <EX> or <ANNOTATION> */
2144 mbtowc(&wnl, "\n", 1);
2145 mbtowc(&wsp, " ", 1);
2147 /* terminate the term string */
2148 if (termp - term > MAXTERM) termp = &term[MAXTERM];
2151 /* make a copy - will transform to match definition transformations */
2152 w_strcpy(dterm, term);
2153 termp = dterm + (termp - term);
2155 /* Check if it should be entered into the glossary structure */
2156 if (vgloss(gloss) == GLOSS)
2158 /* strip possible newlines out of base form */
2161 for (p = base; *p ; p++)
2163 if ((p - base) >= MAXTERM)
2165 if ((p - base) == MAXTERM)
2167 M_WCHAR *wc_stago, *wc_tagc;
2169 wc_stago = MakeWideCharString(m_stago);
2170 wc_tagc = MakeWideCharString(m_tagc);
2171 m_err2("Too many characters in BASEFORM for %sTERM%s",
2174 m_free(wc_stago,"wide character string");
2175 m_free(wc_tagc,"wide character string");
2182 if (*p == wnl) *p = wsp;
2187 /* strip possible newlines out of dterm */
2188 for (p = dterm; *p ; p++)
2190 if (*p == wnl) *p = wsp;
2193 /* trim possible last space */
2194 if (termp - dterm > 1 && *(termp-1) == wsp)
2199 idn = (intptr_t) m_lookfortrie(base ? base : dterm, >ree);
2205 m_ntrtrie(base ? base : dterm, >ree, (void *) (intptr_t) idn);
2209 /* Handle the output */
2210 if (vgloss(gloss) == GLOSS)
2213 "<LINK WINDOW=\"%s\" RID=\"%s%d\">",
2217 mb_strcode(buffer, outfile);
2220 mb_strcode("<KEY CLASS=\"TERM\">", outfile);
2223 if (m_mblevel("EXAMPLESEG"))
2225 /* Are we in one of these? May need to number a line. */
2226 for(p = term; *p; p++)
2233 multi_cr_flag = FALSE;
2234 strcode(term, outfile);
2236 mb_strcode("</KEY>", outfile);
2238 if (vgloss(gloss) == GLOSS)
2240 mb_strcode("</LINK>", outfile);
2243 if (echo) mb_echohead("++");
2246 #if defined(M_PROTO)
2247 M_WCHAR wc_toupper(M_WCHAR wc)
2249 M_WCHAR wc_toupper(wc)
2253 if ((wc >= 0) && (wc <= 255))
2255 return _toupper(wc);
2260 #if defined(M_PROTO)
2261 M_WCHAR *wc_stringtoupper(M_WCHAR *wcp)
2263 M_WCHAR *wc_stringtoupper(wcp)
2267 M_WCHAR *newstring, *nsp;
2270 m_malloc(w_strlen(wcp) + 1, "wide character upper case string");
2274 *nsp = wc_toupper(*wcp);
2292 static char *pLang = NULL;
2296 pLang = MakeMByteString(helplang);
2304 static char *pCharset = NULL;
2308 pCharset = MakeMByteString(helpcharset);
2315 #if defined(M_PROTO)
2316 void HandleLink(M_WCHAR *hyperlink, M_WCHAR *type, M_WCHAR *description)
2318 void HandleLink(hyperlink, type, description)
2321 M_WCHAR *description;
2324 char *mb_hyperlink, mb_undefined[64];
2325 char buffer[BIGBUF];
2326 static M_WCHAR wsp = 0;
2330 mbtowc(&wsp, " ", 1);
2333 strcpy(mb_undefined, sdlReservedName);
2334 strcpy(mb_undefined + SDLNAMESIZ - 1, "-UNDEFINED");
2336 mb_strcode("<LINK ", outfile);
2337 global_linktype = 0; /* default to type jump */
2340 /* type is set, choose which is correct */
2341 if (m_wcmbupstrcmp(type, QJUMP))
2342 { /* not type jump */
2343 if (!m_wcmbupstrcmp(type, QJUMPNEWVIEW))
2344 { mb_strcode("WINDOW=\"NEW\" ", outfile); global_linktype = 1;}
2345 else if (!m_wcmbupstrcmp(type, QDEFINITION))
2346 { mb_strcode("WINDOW=\"POPUP\" ", outfile); global_linktype = 2;}
2347 else if (!m_wcmbupstrcmp(type, QEXECUTE))
2348 { global_linktype = 3;}
2349 else if (!m_wcmbupstrcmp(type, QMAN))
2350 { mb_strcode("WINDOW=\"POPUP\" ", outfile); global_linktype = 4;}
2351 else if (!m_wcmbupstrcmp(type, QAPPDEFINED))
2352 { global_linktype = 5;}
2355 mb_strcode("RID=\"", outfile);
2358 mb_hyperlink = MakeMByteString(hyperlink);
2359 if (*mb_hyperlink == '_') /* must be metainfo */
2361 strcpy(buffer, sdlReservedName);
2362 buffer[SDLNAMESIZ-1] = '-';
2363 strcpy(buffer+SDLNAMESIZ, mb_hyperlink+1);
2364 mb_free(&mb_hyperlink);
2371 "Error: %sLINK%s hyperlink was undefined.\n",
2375 "Error: %sLINK%s hyperlink was undefined.\n",
2379 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
2387 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
2394 m_errline("Use ``hyperlink='' if the value contains non-alphabetics");
2396 mb_hyperlink = mb_undefined;
2399 if ((global_linktype <= 2) && hyperlink && (!w_strchr(hyperlink, wsp)))
2402 sprintf(buffer, "%s", mb_hyperlink);
2406 char tmpsnb[BIGBUF];
2409 int nextId = NextId();
2410 sprintf(buffer, "%s%d", sdlReservedName, nextId);
2411 if (!savesnb && snbstart)
2413 fprintf(snbfp, "%d\n", snbstart);
2416 switch (global_linktype)
2419 case 1: /* jump new */
2420 case 2: /* definition */
2422 "<CROSSDOC ID=\"%s%d\" XID",
2426 case 3: /* execute */
2428 "<SYS-CMD ID=\"%s%d\" COMMAND",
2434 "<MAN-PAGE ID=\"%s%d\" XID",
2438 case 5: /* app defined */
2440 "<CALLBACK ID=\"%s%d\" DATA",
2447 snblen = strlen(savesnb);
2448 savesnb = mb_realloc(savesnb, snblen + strlen(tmpsnb) + 1);
2449 strcpy(savesnb + snblen, tmpsnb);
2450 sprintf(tmpsnb, "=\"%s\">\n", mb_hyperlink);
2451 snblen = strlen(savesnb);
2452 savesnb = mb_realloc(savesnb, snblen + strlen(tmpsnb) + 1);
2453 strcpy(savesnb + snblen, tmpsnb);
2457 fputs(tmpsnb, snbfp);
2458 fprintf(snbfp, "=\"%s\">\n", mb_hyperlink);
2461 mb_strcode(buffer, outfile);
2462 mb_strcode("\"", outfile);
2463 if (mb_hyperlink && (mb_hyperlink != mb_undefined))
2464 m_free(mb_hyperlink,"multi-byte string");
2467 char *mb_description;
2469 mb_description = MakeMByteString(description);
2470 sprintf(buffer, " DESCRIPT=\"%s\"", mb_description);
2471 mb_strcode(buffer, outfile);
2472 m_free(mb_description,"multi-byte string");
2474 mb_strcode(">", outfile);
2478 #if defined(M_PROTO)
2479 char *mb_realloc(char *ptr, long size)
2481 char *mb_realloc(ptr, size)
2489 ssize = (size_t) size;
2490 vptr = realloc((void *) ptr, ssize);
2495 fprintf(stdout, "realloc 0x%p 0x%p\n", ptr, vptr);
2500 return (char *) vptr;
2504 #if defined(M_PROTO)
2505 char *mb_malloc(long size)
2507 char *mb_malloc(size)
2514 ssize = (size_t) size;
2515 cptr = (char *) malloc(ssize);
2518 fprintf(stdout, "malloc 0x%p\n", cptr);
2527 #if defined(M_PROTO)
2528 void mb_free(char **pptr)
2536 fprintf(stdout, "free 0x%p\n", *pptr);
2540 free((void *) *pptr);
2544 #if defined(M_PROTO)
2545 static void AddToRowVec(int *length, char **rowvec, char *id)
2547 static void AddToRowVec(length, rowvec, id)
2553 char tempRowVec[BIGBUF];
2556 sprintf(tempRowVec, "<FROWVEC CELLS=\"%s\">\n", id);
2557 rowVecLen = strlen(tempRowVec);
2558 *rowvec = mb_realloc(*rowvec, *length + rowVecLen);
2559 strcpy(*rowvec + *length - 1, tempRowVec);
2560 *length += rowVecLen;
2564 #if defined(M_PROTO)
2565 void Add2ToRowVec(int *length, char **rowvec, char *id1, char *id2)
2567 void Add2ToRowVec(length, rowvec, id1, id2)
2573 char tempRowVec[BIGBUF];
2576 sprintf(tempRowVec, "<FROWVEC CELLS=\"%s %s\">\n", id1, id2);
2577 rowVecLen = strlen(tempRowVec);
2578 *rowvec = mb_realloc(*rowvec, *length + rowVecLen);
2579 strcpy(*rowvec + *length - 1, tempRowVec);
2580 *length += rowVecLen;
2584 #if defined(M_PROTO)
2585 void StartEx(M_WCHAR *notes, M_WCHAR *lines, M_WCHAR *textsize)
2587 void StartEx(*notes, *lines, *textsize)
2593 exTextSize = vextextsize(textsize);
2594 stackex = vstack(notes);
2596 StartBlock(NULL, "EX", NULL);
2598 tonumexlines = (LOGICAL) (vnumber(lines) == NUMBER);
2602 saveex = mb_malloc(1);
2607 #if defined(M_PROTO)
2616 char buffer[BIGBUF];
2621 if (exTextSize == SMALLEST)
2623 else if (exTextSize == SMALLER)
2627 length = sprintf(buffer, "<P TYPE=\"LITERAL\" SSI=\"EX-%s\">", ssi);
2631 length += sprintf(buffer + length,
2632 "<HEAD TYPE=\"LINED\" SSI=\"EX-NUM\">");
2633 while (oldExLineNum <= exLineNum)
2635 length += sprintf(buffer + length, "%2d:\n", oldExLineNum);
2638 length += sprintf(buffer + length, "</HEAD>");
2643 annotation = MakeMByteString(savehead);
2644 annotLen = strlen(annotation);
2651 saveex = mb_realloc(saveex,
2652 svexlen + length + (svexseglen - 1) + annotLen + 5);
2654 strcpy(saveex + svexlen - 1, buffer);
2659 strcpy(saveex + svexlen - 1, annotation);
2660 svexlen += annotLen;
2663 strcpy(saveex + svexlen - 1, saveexseg);
2664 svexlen += svexseglen - 1;
2666 strcpy(saveex + svexlen - 1, "</P>\n");
2668 mb_free(&saveexseg);
2671 m_free(annotation, "multi-byte string");
2676 #if defined(M_PROTO)
2677 void StartNCW(char *which)
2679 void StartNCW(which)
2684 PushForm(NULL, which, NULL);
2688 #if defined(M_PROTO)
2689 void StartBlock(char *pclass, char *ssi, char *id)
2691 void StartBlock(pclass, ssi, id)
2692 char *pclass, *ssi, *id;
2700 fputs("<FDATA>\n", outfile);
2705 fputs("</BLOCK>\n", outfile);
2708 if (formStackBase && (formStackTop >= formStackBase))
2709 { /* there is a <form> in progress */
2712 sprintf(localId, "%s%d", sdlReservedName, NextId());
2715 AddToRowVec(&(formStackTop->vecLen), &(formStackTop->rowVec), realId);
2718 fputs("<BLOCK", outfile);
2720 fprintf(outfile, " ID=\"%s\"", realId);
2722 fprintf(outfile, " CLASS=\"%s\"", pclass);
2724 fprintf(outfile, " SSI=\"%s\"", ssi);
2725 fputs(">\n", outfile);
2728 firstPInBlock = TRUE;
2732 #if defined(M_PROTO)
2733 void StartNCWtext(char *which, char *iconFile, char *headingString)
2735 void StartNCWtext(which, iconFile, headingString)
2738 char *headingString;
2741 char *icon, *heading;
2743 /* Write default head if no user-specified head was encountered */
2746 heading = GetDefaultHeaderString(headingString, M_SDATA, which);
2747 fprintf(outfile, "<HEAD SSI=\"NCW\">%s", heading);
2748 fputs("</HEAD>\n", outfile);
2750 m_free(heading, "default header string return");
2753 icon = GetDefaultHeaderString(iconFile, M_SYSTEM, "");
2758 sprintf(id, "%s%d", sdlReservedName, NextId());
2760 "<HEAD SSI=\"NCW-ICON\"><SNREF>\n<REFITEM RID=\"%s\" ",
2762 fputs("CLASS=\"ICON\" SSI=\"NCW-ICON\">", outfile);
2763 fputs("</REFITEM>\n</SNREF></HEAD>\n", outfile);
2765 m_free(icon, "icon name");
2770 #if defined(M_PROTO)
2771 void AddToSNB(char *id, char *xid)
2773 void AddToSNB(id, xid)
2778 char tmpsnb[BIGBUF];
2783 sprintf(tmpsnb, "<GRAPHIC ID=\"%s\" XID=\"%s\">\n", id, xid);
2784 snblen = strlen(savesnb);
2785 savesnb = mb_realloc(savesnb, snblen + strlen(tmpsnb) + 1);
2786 strcpy(savesnb + snblen, tmpsnb);
2792 fprintf(snbfp, "%d\n", snbstart);
2795 fprintf(snbfp, "<GRAPHIC ID=\"%s\" XID=\"%s\">\n", id, xid);
2800 #if defined(M_PROTO)
2806 char pathbuf[BIGBUF];
2807 char *try = pathbuf;
2808 int tryleng = sizeof(pathbuf);
2813 M_WCHAR *wc_try, *wc_outputname;
2815 char filebuf[BIGBUF];
2817 char **tossline = toss;
2819 /* the code below assume the extensions are .htg, .tss and .sdl */
2820 /* or at least that all extensions are 3 character plus a dot */
2822 fileleng = w_strlen(inputname);
2823 mb_inputname = mb_malloc(fileleng + 1);
2824 wcstombs(mb_inputname, inputname, fileleng);
2825 strcpy(mb_inputname + fileleng - 4, ".tss");
2831 pathleng = strlen(thispath->directory);
2832 if ((pathleng + fileleng) >= tryleng)
2834 tryleng = pathleng + fileleng + 1;
2836 try = mb_malloc(tryleng);
2838 try = mb_realloc(try, tryleng);
2840 strcpy(try, thispath->directory);
2841 strcpy(try + pathleng, mb_inputname);
2842 tossfile = open(try, O_RDONLY);
2843 if (tossfile >= 0) break;
2844 thispath = thispath->next;
2849 fputs("<TOSS>\n", outfile);
2850 while ((bytesread = read(tossfile, filebuf, sizeof(filebuf))) > 0)
2854 outfile) != bytesread) break;
2857 strcpy(mb_inputname + fileleng - 4, ".sdl");
2858 wc_outputname = MakeWideCharString(mb_inputname);
2859 wc_try = MakeWideCharString(try);
2860 m_err2("error copying %s to output (%s) as the <toss> element",
2863 m_free(wc_try, "wide character toss input name");
2864 m_free(wc_outputname, "wide character output name");
2867 fputs("</TOSS>\n", outfile);
2873 fputs(*tossline++, outfile);
2874 fputs("\n", outfile);
2878 if (try != pathbuf) mb_free(&try);
2881 /* Below is a modified version of m_cyclent() that returns a pointer
2882 * to the entity content rather than its value. Returning a pointer
2883 * to the entity's content field allows it to be modified.
2885 /* Cyclent.c contains procedure m_cyclent(), callable by interface
2886 designers, to cycle through all defined entities, returning information
2888 #if defined(M_PROTO)
2889 M_WCHAR *CycleEnt(LOGICAL init,
2890 unsigned char *type,
2892 unsigned char *wheredef)
2894 M_WCHAR *m_cyclent(init, type, content, wheredef)
2896 unsigned char *type ;
2897 M_WCHAR ***content ;
2898 unsigned char *wheredef ;
2901 static M_TRIE *current ;
2902 static M_TRIE *ancestor[M_NAMELEN + 1] ;
2904 static M_WCHAR name[M_NAMELEN + 1] ;
2908 current = m_enttrie->data ;
2912 if (length < 0) return(NULL) ;
2914 while (current->symbol)
2916 ancestor[length] = current ;
2917 name[length++] = current->symbol ;
2918 current = current->data ;
2920 name[length] = M_EOS ;
2922 *type = ((M_ENTITY *) current->data)->type ;
2923 *content = &(((M_ENTITY *) current->data)->content) ;
2924 *wheredef = ((M_ENTITY *) current->data)->wheredef ;
2930 current = current->next ;
2934 if (length < 0) break ;
2935 current = ancestor[length] ;
2941 /* A routine to examine all defined entities looking for ones of type
2942 * M_SDATA. When found, if the entity's content is of the form
2943 * [......] (six characters surrounded by square brackets), its
2944 * content is modified to be <SPC NAME="[......]"> so that it may be
2945 * emitted into the SDL output.
2947 void ModifyEntities()
2950 unsigned char wheredef;
2954 M_WCHAR *newContent;
2955 static char mb_newContent[] = "<SPC NAME=\"[123456]\">";
2957 name = CycleEnt(TRUE, &type, &content, &wheredef);
2960 mb_newContent[21] = '\0';
2963 if ((type == M_SDATA) && *content)
2965 mb_content = MakeMByteString(*content);
2966 if ((strlen(mb_content) == 8) &&
2967 (mb_content[0] == '[') &&
2968 (mb_content[7] == ']'))
2970 strncpy(mb_newContent+11, mb_content, 8);
2971 if (wheredef == M_DPARSER)
2972 m_free(*content, "old SDATA entity content");
2973 *content = MakeWideCharString(mb_newContent);
2975 m_free(mb_content, "multi-byte SDATA entity content");
2978 while (name = CycleEnt(FALSE, &type, &content, &wheredef));
2982 #if defined(M_PROTO)
2983 void PushForm(char *class, char *ssi, char *id)
2985 void PushForm(class, ssi, id)
2991 char localId[SDLNAMESIZ+10];
2997 fputs("<FDATA>\n", outfile);
3003 fputs("</BLOCK>\n", outfile);
3008 if (formStackBase && (formStackTop >= formStackBase))
3009 { /* there is a <form> in progress */
3012 sprintf(localId, "%s%d", sdlReservedName, NextId());
3015 AddToRowVec(&(formStackTop->vecLen), &(formStackTop->rowVec), realId);
3018 if (formStackTop == formStackMax)
3022 formStackBase = (FORMINFO *) malloc(10 * sizeof(FORMINFO));
3023 formStackTop = formStackBase;
3024 formStackMax = formStackBase + 9;
3028 stackSize = formStackMax - formStackBase + 1;
3030 realloc(formStackBase, (stackSize + 10) * sizeof(FORMINFO));
3031 formStackTop = formStackBase + stackSize;
3032 formStackMax = formStackBase + (stackSize + 9);
3038 formStackTop->rowVec = mb_malloc(1);
3039 formStackTop->vecLen = 1;
3041 fputs("<FORM", outfile);
3043 fprintf(outfile, " ID=\"%s\"", realId);
3045 fprintf(outfile, " CLASS=\"%s\"", class);
3047 fprintf(outfile, " SSI=\"%s\"", ssi);
3048 fputs(">\n", outfile);
3053 #if defined(M_PROTO)
3054 void PushForm2(char *class, char *ssi, char *id1, char *id2)
3056 void PushForm2(class, ssi, id1, id2)
3069 fputs("<FDATA>\n", outfile);
3075 fputs("</BLOCK>\n", outfile);
3081 sprintf(id, "%s%d", sdlReservedName, formId = NextId());
3085 if (formStackBase && (formStackTop >= formStackBase))
3086 { /* there is a <form> in progress */
3087 Add2ToRowVec(&(formStackTop->vecLen),
3088 &(formStackTop->rowVec),
3093 if (formStackTop == formStackMax)
3097 formStackBase = (FORMINFO *) malloc(10 * sizeof(FORMINFO));
3098 formStackTop = formStackBase;
3099 formStackMax = formStackBase + 9;
3103 stackSize = formStackMax - formStackBase + 1;
3105 realloc(formStackBase, (stackSize + 10) * sizeof(FORMINFO));
3106 formStackTop = formStackBase + stackSize;
3107 formStackMax = formStackBase + (stackSize + 9);
3113 formStackTop->rowVec = mb_malloc(1);
3114 formStackTop->vecLen = 1;
3116 fprintf(outfile, "<FORM ID=\"%s\"", id2);
3118 fprintf(outfile, " CLASS=\"%s\"", class);
3120 fprintf(outfile, " SSI=\"%s\"", ssi);
3121 fputs(">\n", outfile);
3129 fputs("</BLOCK>\n", outfile);
3134 "</FDATA>\n<FSTYLE>\n%s</FSTYLE>\n</FORM>\n",
3135 formStackTop->rowVec);
3137 mb_free(&(formStackTop->rowVec));
3145 fputs("</BLOCK>\n", outfile);
3150 "</FDATA>\n<FSTYLE NCOLS=\"2\">\n%s</FSTYLE>\n</FORM>\n",
3151 formStackTop->rowVec);
3153 mb_free(&(formStackTop->rowVec));
3157 /* look to see if there's an open form with no data; if so, add a data
3158 * block and close the form. This situation will happen when a form
3159 * is pushed but the source doesn't go to text either because the text
3160 * is explicitly optional or due to the fact that text can be null.
3164 if ((formStackTop >= formStackBase) && (formStackTop->vecLen == 1))
3166 StartBlock(NULL, NULL, NULL);
3171 void EmitSavedAnchors()
3173 char buffer[BIGBUF];
3178 "<ANCHOR ID=\"%s%d\">",
3181 mb_strcode(buffer, outfile);
3190 fputs("<BLOCK>\n<P>", outfile);
3192 fputs("</P>\n</BLOCK>", outfile);
3194 fputs("</VIRPAGE>\n", outfile);