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:11 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 /* osf has the same function defined, change the routine name to fbasename() */
65 void fbasename(M_NOPAR)
70 char fileListErr[] = "filelist.err";
75 m_error("Specify input file");
79 if ((m_argc > 2) && (strchr(m_argv[2], 'f') || strchr(m_argv[2], 'F')))
82 /* Get installation directory */
83 #define CONTRIB "/usr/dt/bin/"
85 /* get our path if we can */
86 /* A hacked up ``which'', just to find our directory */
87 /* fills ``install'' with path to ourself */
97 if ( *(m_argv[0]) == '/' )
99 /* fully qualified path to ourself was specified */
100 if (access(m_argv[0],1) == 0)
102 /* if full path name exists and is executable */
103 /* get the dirname */
104 for (p = m_argv[0]; *p ; p++) ; /* end of string, (the hard way) */
105 /* backup to dirsep */
108 if (p < m_argv[0]) m_error("Internal Error.");
109 if (*p == dirsep) break;
111 p++; /* just past the dirsep */
114 install = (char *) m_malloc(strlen(m_argv[0]) + 1,
115 "installation directory");
116 strcpy(install, m_argv[0]);
119 none = 0; /* we've got it. */
123 m_error("Internal Error (which).");
128 /* not fully specified, check each component of path for ourself */
129 strcpy(patbuf, getenv("PATH"));
135 cp = strchr(path, ':');
140 sprintf(buf, "%s/%s", path, m_argv[0]);
142 if (access(buf, 1) == 0)
144 install = (char*) m_malloc(strlen(path) + 1,
145 "installation directory");
146 strcpy(install, path);
149 /* else, not an error if we can't find a particular one. */
154 break; /* either out of paths, or we found it. */
161 /* can't get it, use default */
162 install = (char *) m_malloc(strlen(CONTRIB) + 1,
163 "installation directory");
164 strcpy(install, CONTRIB);
166 /* else -- we've got it */
169 /* Set default working directory (from input filename) */
170 for (p = strchr(m_argv[1], M_EOS); p > m_argv[1] ; p--)
171 if (*(p - 1) == dirsep)
177 work = (char *) m_malloc(strlen(m_argv[1]) + 1, "working directory");
178 strcpy(work, m_argv[1]);
179 indir = (char *) m_malloc(strlen(m_argv[1]) + 1, "input directory");
180 strcpy(indir, m_argv[1]);
188 /* Build base name */
189 q = strchr(m_argv[1], M_EOS);
190 while ((q > m_argv[1]) && (*q != '.') && (*q != dirsep))
192 defaultext = (LOGICAL) (*q != '.');
193 if (! defaultext) *q = M_EOS;
194 nodirbase = (char *) m_malloc(strlen(p) + 1,
195 "basename without directory");
196 strcpy(nodirbase, p);
197 /* Get working directory option, if specified */
199 base = (char *) m_malloc(n + strlen(".ctg") + 1, "basename");
202 baseext = base + n + 1;
207 options(TRUE); /* pluck only length changing optins */
210 /* Build short versions of basename */
211 /* set up global helpbase and helpext */
212 helpbase = (char *) m_malloc(strlen(work) +
214 PRE_EXTENSION_LIMIT +
218 strcpy(helpbase, work);
219 strncat(helpbase, nodirbase, BASENAME_LIMIT);
220 helpext = helpbase + strlen(helpbase);
223 { /* Build long names */
224 /* set up global helpbase and helpext */
225 helpbase = (char *) m_malloc(strlen(work) +
227 PRE_EXTENSION_LIMIT +
231 strcpy(helpbase, work);
232 strcat(helpbase, nodirbase);
233 helpext = helpbase + strlen(helpbase);
236 /* Open error files */
239 p = mb_malloc(strlen(work)+sizeof(fileListErr));
241 strcat(p, fileListErr);
242 m_openchk(&m_errfile, p, "w");
247 strcpy(helpext, ".err");
248 m_openchk(&m_errfile, helpbase, "w");
253 /* This procedure starts a CHAPTER */
262 char *chapterPrefixString =
263 GetDefaultHeaderString("ChapterElementDefaultHeadingString",
266 char *chapterSuffixString =
267 GetDefaultHeaderString("ChapterSuffixElementDefaultHeadingString",
275 m_itoa(chapter, chapstring);
287 chapterSuffixString);
288 m_free(chapterPrefixString, "GetDefaultHeaderString return");
289 if (*chapterSuffixString)
290 m_free(chapterSuffixString, "GetDefaultHeaderString return");
294 /* Called at end of manual to report terms that occurred in the document
295 but not entered in the glossary */
296 void checkgloss(M_NOPAR)
299 M_WCHAR id[MAXTERM + 1];
300 M_TRIE *node[MAXTERM + 1];
303 if (! gtree.data) return;
305 current = gtree.data;
308 id[n] = current->symbol;
309 node[n] = current->next;
312 if ((intptr_t) current->data >= 0)
313 m_err1("No glossary definition for %s", id);
314 current = current->next;
324 current = current->data;
331 /* End Error Message macro \starterrmsg call, check to see if Error Message
332 head is user specified or default */
333 void checkmsghead(M_NOPAR)
336 GetDefaultHeaderString("MessagesElementDefaultHeadingString",
339 if (emsghead == DEFHEAD)
340 { /* head not output yet */
341 fprintf(outfile, "<HEAD CLASS=\"HEAD\">%s</HEAD>\n", string);
344 else if (emsghead == USERHEAD)
345 { /* user specified head */
348 m_free(string, "GetDefaultHeaderString return");
349 } /* end checkmsghead() */
352 /* construct a qualified file name */
354 static int mb_getqualified(char *qualname, char *unqualname)
356 static int mb_getqualified(qualname, unqualname)
361 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(__osf__) || defined(linux) || defined(CSRG_BASED)
366 char tokstr [ 20 ], *gp, *p, *pp, *fnp, curdir[FNAMELEN-1];
367 int roomleft = FNAMELEN - 1;
375 if (strlen(unqualname) < (size_t) FNAMELEN)
376 strcpy(fn, unqualname );
379 m_mberr1("Internal Error. File name too long for qualifying: %s",
386 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(__osf__) || defined(linux) || defined(CSRG_BASED)
388 gp = qualname + strlen(qualname);
389 roomleft = roomleft - strlen(qualname);
391 /* if path is from root, tack that on, else tack on the current
392 directory (for the referenced drive, if MS-DOS) */
393 /* We assume FNAMELEN is at least three (3), so no range checking here */
396 strcat(qualname, SSEP);
402 f = popen("/bin/pwd", "r");
405 if (strlen(gp) >= (size_t) roomleft)
407 m_mberr1("Internal error: possible stray pointer in getqualified(): %s",
411 strcat(qualname,SSEP);
415 /* if MS-DOS, force to upper case, then get drive spec */
417 if ( fn[1] == ':' ) {
418 strncpy ( qualname, fn, 2 );
422 getcwd(qualname, roomleft);
425 gp = qualname + strlen ( qualname );
426 roomleft = roomleft - strlen ( qualname );
427 /* if path is from root, tack that on, else tack on the current
428 directory (for the referenced drive, if MS-DOS) */
429 if ( *fnp == CSEP ) {
430 strcat ( qualname, SSEP );
435 /* assume current directory always !!! */
437 getcwd(curdir, FNAMELEN-1);
438 if (*curdir != *qualname) {
439 m_err1("Relative directory %s for non-current drive, can't qualify",
443 if (strlen(curdir) > 3) {
444 if ((strlen(curdir+3)+1) < roomleft) { /* "1" for SSEP */
445 strcpy( gp+1, curdir+3 );
446 strcat ( qualname, SSEP );
447 roomleft = roomleft - strlen(curdir+3) - 1; /* "1" for SSEP */
450 m_err1("Internal error. File name too long for qualifying: %s",
458 strcpy(tokstr, " \r\n\t");
459 strcat(tokstr, SSEP);
462 p = strtok(( p == NULL ) ? fnp : NULL, tokstr);
463 if ( p == NULL ) break;
464 if ( *p == '.' ) /* alias */
466 if ( *(p+1) == '.' ) /* parent */
468 *strrchr(qualname, CSEP) = '\0';
469 pp = strrchr(qualname, CSEP);
470 if (pp == NULL) /* FAIL */
472 m_mberr1("Internal error. Failed in qualifying %s", unqualname);
483 if ((strlen(p)+1) < (size_t) roomleft)
486 strcat(qualname, SSEP);
487 roomleft = roomleft - strlen(p) - 1;
491 m_mberr1("Internal error. File name too long for qualifying: %s",
498 *strrchr(qualname, CSEP) = '\0';
500 #if defined(hpux) || defined(_AIX) || defined(sun) || defined(USL) || defined(__uxp__) || defined(__osf__) || defined(linux) || defined(CSRG_BASED)
506 } /* end mb_getqualified */
509 int getqualified (qualname, unqualname)
514 char mb_qualname[FNAMELEN],
515 mb_unqualname[FNAMELEN];
517 wcstombs(mb_qualname, qualname, FNAMELEN);
518 wcstombs(mb_unqualname, unqualname, FNAMELEN);
520 retval = mb_getqualified(mb_qualname, mb_unqualname);
522 mbstowcs(qualname, mb_qualname, FNAMELEN);
523 mbstowcs(unqualname, mb_unqualname, FNAMELEN);
529 /* handle the common link and graphic code for <p> and <image> */
531 handle_link_and_graphic(parent,
537 M_WCHAR *parent, *gentity, *gposition, *ghyperlink, *glinktype, *gdescription;
539 unsigned char etype, wheredef;
540 char *mb_content, *ssi, id[32];
541 static M_WCHAR empty = M_EOS;
544 /* handle graphic specific code */
545 /* initialize some stuff first:
546 - file is the entity name,
547 - f_file is the content of the entity, used only if f_content nonNULL
548 - f_content is f_file with the relative pathname, initialized to NULL,
549 - f_contqual is fully qualified f_file, assigned ONLY IF
554 f_contqual[0] = M_EOS;
556 /* get the position, default to left */
560 M_WCHAR *wc_left, *wc_right;
562 wc_right = MakeWideCharString(QRIGHT);
563 if (!m_wcupstrcmp(gposition, wc_right))
569 wc_left = MakeWideCharString(QLEFT);
570 if (m_wcupstrcmp(gposition, wc_left))
572 m_err1("Invalid value for gposition: `%s'", gposition);
574 m_free(wc_left,"wide character string");
576 m_free(wc_right,"wide character string");
579 /* check ENTITY and determine the figure type */
582 m_lookent(gentity, &etype, &f_file, &wheredef);
583 if (etype != M_SYSTEM)
585 M_WCHAR *wc_entsystem, *wc_entkw, *wc_stago, *wc_tagc;
587 wc_entsystem = MakeWideCharString(m_entsystem);
588 wc_entkw = MakeWideCharString(m_entkw);
589 wc_stago = MakeWideCharString(m_stago);
590 wc_tagc = MakeWideCharString(m_tagc);
592 "%s not a %s %s, as required for the ENTITY parameter of %s%s%s",
599 m_free(wc_entsystem,"wide character string");
600 m_free(wc_entkw,"wide character string");
601 m_free(wc_stago,"wide character string");
602 m_free(wc_tagc,"wide character string");
607 f_content = searchforfile(f_file);
610 if (getqualified(f_contqual, f_content))
612 /* unsuccessful qual */
613 if (w_strlen(f_content) < FNAMELEN)
614 w_strcpy(f_contqual, f_content);
617 m_err1("Internal error. File name too long: %s",
625 m_err2("Can't find file %s (declared in entity %s)",
630 if (!f_content) f_content = ∅
632 mb_content = MakeMByteString(f_content);
633 sprintf(id, "%s%d", sdlReservedName, NextId());
634 ssi = MakeMByteString(m_parent(0));
635 fprintf(outfile, "<HEAD SSI=\"%s-GRAPHIC-%s\">", ssi, leftright);
637 HandleLink(ghyperlink, glinktype, gdescription);
638 fprintf(outfile, "<SNREF>\n<REFITEM RID=\"%s\" ", id);
639 fputs("CLASS=\"FIGURE\"", outfile);
640 AddToSNB(id, mb_content);
641 m_free(mb_content,"multi-byte string");
644 /* and finish the position now */
647 fprintf(outfile, " SSI=\"GRPH-%s\"", leftright);
652 fputs("></REFITEM></SNREF>", outfile);
654 fputs("</LINK>", outfile);
655 fputs("</HEAD>", outfile);
658 if (!ghyperlink && (glinktype || gdescription))
662 "Error: %sP%s ghyperlink was undefined.\n",
666 "Error: %sP%s ghyperlink was undefined.\n",
670 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
678 "Beware of using a reserved value such as:\n%s, %s, %s, %s, %s, or %s.\n",
685 m_errline("Use ``ghyperlink='' if the value contains non-alphabetics");
690 /* Process an item in a list */
692 void Item(M_WCHAR *id)
698 char orderString[32];
699 static char *ROMAN0[] =
700 {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
701 static char *ROMAN10[] =
702 {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
703 static char *ROMAN100[] =
704 {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
705 static char ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
706 static char *roman0[] =
707 {"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"};
708 static char *roman10[] =
709 {"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"};
710 static char *roman100[] =
711 {"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"};
712 static char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
713 static char numbers[] = "0123456789";
714 static char romanString[] = "ROMAN";
715 static char alphaString[] = "ALPHA";
716 static char arabicString[] = "ARABIC";
717 int count, metaCount;
719 char label_id[SDLNAMESIZ+10];
724 LOGICAL isBullet, isLoose, isFirst;
728 if (listitems[list].firstitem)
730 listitems[list].firstitem = FALSE;
733 count = ++lastlist->lastlist->count;
734 if (count > 999) count = 999; /* holy cow! Big list. */
745 if (lastlist->lastlist->space == TIGHT)
754 listtype = lastlist->lastlist->type;
755 if (listtype == BULLET)
758 if ((listtype != PLAIN) && (listtype != MILSPEC))
759 { /* don't emit label for type==PLAIN and type==MILSPEC */
765 pThisBulletId = &firstLooseBulletId;
768 looseBulletIdIndex = (- looseBulletIdIndex) + 1;
769 pThisBulletId = &looseBulletId[looseBulletIdIndex];
775 pThisBulletId = &firstBulletId;
778 bulletIdIndex = (- bulletIdIndex) + 1;
779 pThisBulletId = &bulletId[bulletIdIndex];
783 { /* use an existing block containing a bullet */
784 strcpy(label_id, sdlReservedName);
785 m_itoa(*pThisBulletId, label_id + SDLNAMESIZ - 1);
789 *pThisBulletId = NextId();
790 strcpy(label_id, sdlReservedName);
791 m_itoa(*pThisBulletId, label_id + SDLNAMESIZ - 1);
794 fputs("<FDATA>\n", outfile);
798 "<BLOCK ID=\"%s\" CLASS=\"ITEM\" TIMING=\"ASYNC\" ",
801 "SSI=\"%s%s-BULLET\">\n<P><SPC NAME=\"[bull ]\">",
804 fputs("</P>\n</BLOCK>\n", outfile);
809 strcpy(label_id, sdlReservedName);
810 m_itoa(NextId(), label_id + SDLNAMESIZ - 1);
813 fputs("<FDATA>\n", outfile);
816 fprintf(outfile, "<BLOCK ID=\"%s\" CLASS=\"ITEM\" SSI=\"", label_id);
821 if (listtype == ORDER)
823 orderString[0] = '\0';
824 switch (lastlist->lastlist->order)
827 strcpy(orderString, ROMAN100[count / 100]);
828 strcat(orderString, ROMAN10[(count / 10) % 10]);
829 strcat(orderString, ROMAN0[count % 10]);
834 while ((count -= 26) > 0) metaCount++;
835 count = lastlist->lastlist->count;
836 if (count > 999) count = 999;
839 while (--metaCount >= 0) strncat(orderString, &ALPHABET[count], 1);
843 if (metaCount = (count / 100))
844 strncat(orderString, &numbers[metaCount], 1);
845 if (metaCount || ((count / 10) % 10))
846 strncat(orderString, &numbers[(count / 10) % 10], 1);
847 strncat(orderString, &numbers[count % 10], 1);
851 strcpy(orderString, roman100[count / 100]);
852 strcat(orderString, roman10[(count / 10) % 10]);
853 strcat(orderString, roman0[count % 10]);
858 while ((count -= 26) > 0) metaCount++;
859 count = lastlist->lastlist->count;
860 if (count > 999) count = 999;
863 while (--metaCount >= 0) strncat(orderString, &alphabet[count], 1);
868 "%s%s-%s\">\n<P>%s%c",
873 lastlist->lastlist->punct == DOTPUNCT ? '.' : ')' );
879 sprintf(buffer, "Item %s", orderString);
880 wc = MakeWideCharString(buffer);
881 w_strcpy(xrefstring, wc);
882 m_free(wc,"wide character string");
884 xstrlen = w_strlen(xrefstring);
885 m_getline(&xrffile, &xrfline);
888 /* set to primary input */
900 item_id = MakeMByteString(id);
904 { /* Bullet, Check or Plain list */
905 if (id) m_error("Cross-reference ID in non-ORDER list not allowed");
906 /* already handled Bullet */
907 if (listtype == CHECK)
910 "%s%s-CHECK\">\n<P><SPC NAME=\"[check ]\">",
914 /* don't emit label for listtype==PLAIN and listtype==MILSPEC */
917 if ((listtype != PLAIN) && (listtype != MILSPEC) && (listtype != BULLET))
918 fputs("</P>\n</BLOCK>\n", outfile);
920 sprintf(ssi, "%s%s", first, loose);
921 if ((listtype == PLAIN) || (listtype == MILSPEC))
922 PushForm("ITEM", ssi, item_id);
924 PushForm2("ITEM", ssi, label_id, item_id);
927 m_free(item_id, "multi-byte string");
939 } /* END procedure rsectstart */
942 /* Called at the end of a chapter, appendix, or section to end an open
943 sequence of rsects */
944 void rseqend(M_NOPAR)
952 /* Follow search path to find a file, returning qualified name */
953 M_WCHAR *searchforfile(file)
958 char *mb_file, mb_filename[2048];
959 int dir_leng,file_leng;
961 mb_file = MakeMByteString(file);
962 if (! access(mb_file, READABLE))
964 filename = (M_WCHAR *)
965 m_malloc(w_strlen(file) + 1, "figure/icon filename");
966 w_strcpy(filename, file);
967 m_free(mb_file,"multi-byte string");
971 file_leng = strlen(mb_file);
972 for (searchp = path; searchp ; searchp = searchp->next)
974 if (((dir_leng = strlen(searchp->directory)) + file_leng) >= 2048)
978 wc = MakeWideCharString(searchp->directory);
979 m_err2("%s and %s overflow the file name space", wc, file);
980 m_free(wc,"wide character string");
983 strcpy(mb_filename, searchp->directory);
984 strcpy(mb_filename+dir_leng, mb_file);
985 if (! access(mb_filename, READABLE))
987 m_free(mb_file,"multi-byte string");
988 return(MakeWideCharString(mb_filename));
992 m_free(mb_file,"multi-byte string");
997 /* Start a new helpnode */
999 void starthelpnode(M_WCHAR *ssi,
1003 void starthelpnode(ssi, id, level)
1010 char *mbyte, *mb_ssi;
1011 char mb_nodeid[NODEID_LENGTH+1], nodenum[32];
1013 if (outfile != m_outfile)
1015 m_error("Internal warning: Outfile has been redirected.");
1021 mb_ssi = MakeMByteString(ssi);
1023 /* we can't use the bullet block across virpage boundaries */
1026 looseBulletId[0] = 0;
1027 looseBulletId[1] = 0;
1029 firstLooseBulletId = 0;
1031 /* might as well always start with id 0 (we flip first) */
1033 looseBulletIdIndex = 1;
1035 if ((id == NULL) || (*id == 0))
1037 strcpy(mb_nodeid, sdlReservedName);
1038 m_itoa(NextId(), nodenum);
1039 strcpy(mb_nodeid + SDLNAMESIZ - 1, nodenum);
1040 mbstowcs(nodeid, mb_nodeid, NODEID_LENGTH);
1044 w_strncpy(nodeid, id, NODEID_LENGTH);
1045 wcstombs(mb_nodeid, id, NODEID_LENGTH);
1049 "<VIRPAGE ID=\"%s\" LEVEL=\"%d\" LANGUAGE=\"%s\" CHARSET=\"%s\" DOC-ID=\"%s\" SSI=\"%s\">\n",
1056 m_free(mb_ssi,"multi-byte string");
1057 snbstart = ftell(outfile);
1058 } /* End starthelpnode(id) */
1061 #if defined(M_PROTO)
1062 void mb_starthelpnode(char *ssi,
1066 void mb_starthelpnode(ssi, id, level)
1072 M_WCHAR *wc_ssi, *wc_id;
1076 wc_ssi = MakeWideCharString(ssi);
1079 wc_id = MakeWideCharString(id);
1080 starthelpnode(wc_ssi, wc_id, level);
1082 m_free(wc_ssi,"wide character string");
1084 m_free(wc_id,"wide character string");
1088 /* Start a labeled list */
1089 void StartLabList(spacing, longlabel)
1094 static char def_spacing[] = "LOOSE";
1097 if (list >= MAXLISTLEV)
1098 m_error("Nesting of <LIST> and <LABLIST> too deep");
1101 mb_spacing = MakeMByteString(spacing);
1103 mb_spacing = def_spacing;
1105 sprintf(ssi, "LABELED-%s", mb_spacing);
1106 PushForm("LIST", ssi, NULL);
1108 if (mb_spacing != def_spacing)
1109 mb_free(&mb_spacing);
1113 listitems[list].firstitem = TRUE;
1114 listitems[list].longlabel = vlonglabel(longlabel);
1116 if (list <= MAXLISTLEV)
1118 if (vspacing(spacing) == TIGHT)
1120 lablisttight[list] = TRUE;
1124 lablisttight[list] = FALSE;
1131 #if defined(M_PROTO)
1132 void StartList(M_WCHAR *type,
1137 void StartList(type, order, spacing, cont)
1138 M_WCHAR *type, *order, *spacing, *cont;
1146 static char def_spacing[] = "LOOSE";
1152 mb_spacing = MakeMByteString(spacing);
1156 mb_spacing = def_spacing;
1161 if (list > MAXLISTLEV)
1162 m_error("Nesting of <LIST> and <LABLIST> too deep");
1164 if (! lastlist->started && cont)
1166 m_error("No previous list to continue");
1172 if (order && (vordertype(order) != lastlist->order))
1174 m_error("Unable to continue a list and change the numbering scheme");
1178 if (type && (vtype(type) != lastlist->type))
1180 m_error("Unable to continue a list and change its type");
1186 { /* clear old list? */
1187 for (chain = lastlist->chain; chain ; chain = xchain)
1189 xchain = chain->next;
1190 m_free(chain, "list chain");
1192 lastlist->chain = NULL;
1193 lastlist->count = 0;
1196 /* If outermost list, initialize according to current defaults */
1197 if (! cont && lastlist == &outlist)
1199 outlist.type = vtype(NULL);
1200 outlist.order = vordertype(NULL);
1202 outlist.space = vspacing(NULL);
1203 outlist.punct = DOTPUNCT;
1206 if (type) lastlist->type = vtype(type);
1210 lastlist->type = ORDER;
1211 lastlist->order = vordertype(order);
1214 switch (lastlist->type)
1218 list_type = "PLAIN";
1221 list_type = "CHECK";
1224 list_type = "ORDER";
1228 list_type = "BULLET";
1230 sprintf(ssi, "%s-%s", list_type, mb_spacing);
1232 PushForm("LIST", ssi, NULL);
1234 if (mb_spacing != def_spacing)
1235 m_free(mb_spacing, "multi-byte string");
1238 lastlist->space = LOOSE;
1239 if (spacing && ! m_wcmbupstrcmp(spacing, QTIGHT)) lastlist->space = TIGHT;
1241 if (type && order && m_wcmbupstrcmp(type, QORDER))
1242 m_err2("Incompatible specification for list: %s and %s", type, order);
1244 if (lastlist->type == ORDER)
1246 chain = (CONTCHAIN *) m_malloc(sizeof(CONTCHAIN), "list chain");
1247 chain->next = lastlist->chain;
1248 lastlist->chain = chain;
1249 chain->where = ftell(outfile);
1252 lastlist->started = TRUE;
1253 listitems[list].firstitem = TRUE;
1255 /* Prepare for sublist */
1256 nextlist = (LIST *) m_malloc(sizeof(LIST), "list structure");
1257 nextlist->lastlist = lastlist;
1258 nextlist->type = lastlist->type;
1259 nextlist->punct = lastlist->punct;
1260 if (lastlist->type == ORDER)
1262 nextlist->order = lastlist->order + 1;
1263 if (nextlist->order > LROMAN)
1265 nextlist->order = ARABIC;
1266 nextlist->punct = PARENPUNCT;
1269 else nextlist->order = lastlist->order;
1270 nextlist->count = 0;
1271 nextlist->space = lastlist->space;
1272 nextlist->started = FALSE;
1273 nextlist->where = FIRST;
1274 nextlist->chain = NULL;
1275 lastlist = nextlist;
1282 CONTCHAIN *chain, *xchain ;
1285 curlist = lastlist->lastlist ;
1287 if ((curlist->type == PLAIN) || (curlist->type == MILSPEC))
1294 for (chain = lastlist->chain ; chain ; chain = xchain)
1296 xchain = chain->next ;
1297 m_free(chain, "list chain") ;
1299 m_free(lastlist, "list structure") ;
1300 lastlist = curlist ;
1301 for (chain = lastlist->chain ; chain ; chain = chain->next)
1303 if (lastlist->count > 999)
1305 m_error("Unable to support more than 999 items in an ordered list") ;
1306 lastlist->count = 999 ;
1309 if (lastlist->type == BULLET) bulcount-- ;
1313 /* Open and initialize TeX file */
1314 void texinit(M_NOPAR)
1316 LOGICAL init = TRUE;
1319 unsigned char wheredef;
1330 /* Check .XRF file */
1331 strcpy(helpext, ".xrh");
1332 xrf = fopen(helpbase, "r");
1333 if (! xrf) rebuild = TRUE;
1336 fscanf(xrf, "\\gobble\001");
1337 for (p = m_signon; *p ; p++)
1343 "Output files from different version of Tag, regenerating. . .\n");
1352 while ((ic = getc(xrf)) != EOF)
1353 if (ic == '\n') break;
1354 if (xrf && ic !=EOF)
1355 while ((ic = getc(xrf)) != EOF)
1356 if (ic == '\n') break;
1360 /* Open output files */
1361 strcpy(helpext, ".sdl");
1362 m_openchk(&m_outfile, helpbase, "w");
1363 outfile = m_outfile;
1365 savehelpfilename = (M_WCHAR *)m_malloc(strlen(helpbase)+1, "help file name");
1366 mbstowcs(savehelpfilename, helpbase, strlen(helpbase) + 1);
1369 strcpy(helpext, ".idx");
1370 m_openchk(&indexfp, helpbase, "wb");
1372 /* system notation block file */
1373 strcpy(helpext, ".snb");
1374 m_openchk(&snbfp, helpbase, "wb");
1376 while (name = m_cyclent(init, &type, &content, &wheredef))
1382 if (type == M_SYSTEM)
1383 qfile = searchforfile(content);
1385 if (qfile) m_free(qfile, "figure filename");
1387 if (type == M_SYSTEM)
1389 mbtowc(&wsl, "/", 1);
1391 if (w_strchr(content, wsl))
1393 m_err2("Avoid directory names in FILE entity %s: %s",
1396 m_errline("(Use the SEARCH option instead)\n");
1401 /* Include cross-reference file */
1402 strcpy(helpext, ".xrh");
1404 postpreamble = ftell(outfile);
1408 /* Lookup localized header string entity as defined (by default) in
1409 locallang.ent. If the the header string was not found, or it was
1410 not of type "desiredType", return the default.
1412 If the entity is of type file (M_SYSTEM) then if the content is not
1413 empty search the path for the file. If the file is found, return
1414 its name else return an empty string.
1416 If this routine returns anything other than the empty string (""),
1417 the string returned must be m_free'd.
1420 #if defined(M_PROTO)
1421 GetDefaultHeaderString(
1423 unsigned char desiredType,
1424 char *defaultString )
1426 GetDefaultHeaderString(elementName, desiredType, defaultString)
1428 unsigned char desiredType;
1429 char *defaultString;
1432 unsigned char type,wheredef;
1435 M_WCHAR *wc_elementName;
1439 wc_elementName = MakeWideCharString(elementName);
1440 if (m_lookent(wc_elementName, &type, &content, &wheredef))
1442 if (type == desiredType)
1444 if (type == M_SDATA)
1446 m_free(wc_elementName,"wide character string");
1447 mb_content = MakeMByteString(content);
1450 m_free(mb_content,"multi-byte string");
1458 path = searchforfile(content);
1461 m_err2("Can't find file %s (declared in entity %s)",
1464 m_free(wc_elementName,"wide character string");
1469 m_free(wc_elementName,"wide character string");
1470 return MakeMByteString(path);
1473 m_free(wc_elementName,"wide character string");
1478 m_free(wc_elementName,"wide character string");
1481 retval = m_malloc(strlen(defaultString) + 1,
1482 "GetDefaultHeaderString return");
1483 return strcpy(retval, defaultString);
1490 /* A function that takes a language/charset pair and:
1491 * if they are standard, leave them unchanged but get local
1492 * versions and setlocale(3) using those
1493 * if they are local, setlocale(3) with them and replace them with
1494 * standard versions.
1497 #if defined(M_PROTO)
1498 SetStdLocale(char *pLang, char *pCharset)
1500 SetStdLocale(pLang, pCharset)
1505 static const char *cString = "C";
1506 static const char *isoString = "ISO-8859-1";
1507 _DtXlateDb myDb = NULL;
1508 char myPlatform[_DtPLATFORM_MAX_LEN+1];
1509 char myLocale[256]; /* arbitrarily large */
1517 strcpy(myLocale, pLang);
1520 strcat(myLocale, ".");
1521 strcat(myLocale, pCharset);
1524 if ((_DtLcxOpenAllDbs(&myDb) != 0) ||
1525 (_DtXlateGetXlateEnv(myDb,myPlatform,&execVer,&compVer) != 0))
1528 "Warning: could not open locale translation database.\n");
1529 if (m_errfile != stderr)
1531 "Warning: could not open locale translation database.\n");
1532 strcpy(pLang, cString);
1533 strcpy(pCharset, isoString);
1535 _DtLcxCloseDb(&myDb);
1539 isStd = !_DtLcxXlateOpToStd(myDb,
1550 { /* already standard - get local versions and set locale */
1551 if (_DtLcxXlateStdToOp(myDb,
1554 DtLCX_OPER_SETLOCALE,
1562 "Warning: could not translate CDE locale to local\n");
1563 if (m_errfile != stderr)
1565 "Warning: could not translate CDE locale to local\n");
1566 strcpy(pLang, cString);
1567 strcpy(pCharset, isoString);
1568 _DtLcxCloseDb(&myDb);
1573 setlocale(LC_CTYPE, locale);
1578 { /* already local - set locale and get standard versions */
1579 if (_DtLcxXlateOpToStd(myDb,
1582 DtLCX_OPER_SETLOCALE,
1590 "Warning: could not translate local locale to CDE\n");
1591 if (m_errfile != stderr)
1593 "Warning: could not translate local locale to CDE\n");
1594 strcpy(pLang, cString);
1595 strcpy(pCharset, isoString);
1596 _DtLcxCloseDb(&myDb);
1599 setlocale(LC_CTYPE, myLocale);
1603 strcpy(pLang, lang);
1607 strcpy(pLang, cString);
1611 strcpy(pCharset, charset);
1615 strcpy(pCharset, isoString);
1618 _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))
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 .ctg, .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);