Tons of small fixes to documentation.
[alexxy/gromacs.git] / src / gmxlib / wman.c
1 /*
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * GROningen Mixture of Alchemy and Childrens' Stories
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include "string2.h"
40 #include "smalloc.h"
41 #include "sysstuff.h"
42 #include "filenm.h"
43 #include "macros.h"
44 #include "replace.h"
45 #include "wman.h"
46 #include "statutil.h"
47 #include "copyrite.h"
48 #include "strdb.h"
49 #include "time.h"
50 #include "readinp.h"
51
52 /* The source code in this file should be thread-safe. 
53          Please keep it that way. */
54
55
56 typedef struct {
57   const char *search,*replace;
58 } t_sandr_const;
59
60 typedef struct {
61   char *search,*replace;
62 } t_sandr;
63
64 const t_sandr_const sandrTeX[] = {
65   { "[TT]", "{\\tt " },
66   { "[tt]", "}"      },
67   { "[BB]", "{\\bf " },
68   { "[bb]", "}"      },
69   { "[IT]", "{\\em " },
70   { "[it]", "}"      },
71   { "[PAR]","\n\n"   },
72   /* Escaping underscore for LaTeX is no longer necessary, and it breaks
73    * text searching and the index if you do. */
74   /*
75   { "_",    "\\_"    },
76   */
77   { "$",    "\\$"    },
78   { "<=",   "\\ensuremath{\\leq{}}"},
79   { ">=",   "\\ensuremath{\\geq{}}"},
80   { "<",    "\\textless{}" },
81   { ">",    "\\textgreater{}" },
82   { "^",    "\\^{}"    },
83   { "\\^{}t", "\\ensuremath{^t}" },
84   { "\\^{}a", "\\ensuremath{^a}" },
85   { "\\^{}b", "\\ensuremath{^b}" },
86   { "\\^{}2", "\\ensuremath{^2}" },
87   { "\\^{}3", "\\ensuremath{^3}" },
88   { "\\^{}6", "\\ensuremath{^6}" },
89   { "#",    "\\#"    },
90   { "[BR]", "\\\\"   },
91   { "%",    "\\%"    },
92   { "&",    "\\&"    },
93   /* The next couple of lines allow true Greek symbols to be written to the 
94      manual, which makes it look pretty */
95   { "[GRK]", "$\\"   },
96   { "[grk]", "$"     },
97   /* The next two lines used to substitute "|" and "||" to "or", but only
98    * g_angle used that functionality, so that was changed to a textual
99    * "or" there, so that other places could use those symbols to indicate
100    * magnitudes. */
101   { "||",    "\\textbar{}\\textbar"    },
102   { "|",     "\\textbar{}"    }
103 };
104 #define NSRTEX asize(sandrTeX)
105
106 const t_sandr_const sandrTty[] = {
107   { "[TT]", "" },
108   { "[tt]", "" },
109   { "[BB]", "" },
110   { "[bb]", "" },
111   { "[IT]", "" },
112   { "[it]", "" },
113   { "[PAR]","\n\n" },
114   { "[BR]", "\n"},
115   { "[GRK]", "" },
116   { "[grk]", "" }
117 };
118 #define NSRTTY asize(sandrTty)
119
120 const t_sandr_const sandrWiki[] = {
121   { "&",    "&amp;" },
122   { "<",    "&lt;" },
123   { ">",    "&gt;" },
124   { "[TT]", "&lt;code&gt;" },
125   { "[tt]", "&lt;/code&gt;" },
126   { "[BB]", "'''" },
127   { "[bb]", "'''" },
128   { "[IT]", "''" },
129   { "[it]", "''" },
130   { "[PAR]","\n\n" },
131   { "[BR]", "\n"}
132 };
133 #define NSRWIKI asize(sandrWiki)
134
135 const t_sandr_const sandrNROFF[] = {
136   { "[TT]", "\\fB " },
137   { "[tt]", "\\fR" },
138   { "[BB]", "\\fB " },
139   { "[bb]", "\\fR" },
140   { "[IT]", "\\fI " },
141   { "[it]", "\\fR" },
142   { "[PAR]","\n\n" },
143   { "\n ",    "\n" },
144   { "<",    "" },
145   { ">",    "" },
146   { "^",    "" },
147   { "#",    "" },
148   { "[BR]", "\n"},
149   { "-",    "\\-"}
150 };
151 #define NSRNROFF asize(sandrNROFF)
152
153 const t_sandr_const sandrHTML[] = {
154   { "<",    "&lt;" },
155   { ">",    "&gt;" },
156   { "[TT]", "<tt>" },
157   { "[tt]", "</tt>" },
158   { "[BB]", "<b>" },
159   { "[bb]", "</b>" },
160   { "[IT]", "<it>" },
161   { "[it]", "</it>" },
162   { "[PAR]","<p>" },
163   { "[BR]", "<br>" },
164   { "[GRK]", "&"  },
165   { "[grk]", ";"  }
166 };
167 #define NSRHTML asize(sandrHTML)
168
169 const t_sandr_const sandrXML[] = {
170   { "<",    "&lt;" },
171   { ">",    "&gt;" },
172   { "[TT]", "<arg>" },
173   { "[tt]", "</arg>" },
174   { "[BB]", "<emp>" },
175   { "[bb]", "</emp>" },
176   { "[IT]", "<it>" },
177   { "[it]", "</it>" },
178   { "[PAR]","</par>\n<par>" },
179   { "[BR]", "<br />" }
180 };
181 #define NSRXML asize(sandrXML)
182
183 static void mynum(char *buf,int n)
184 {
185   if (n >= 10)
186     sprintf(buf,"%2d",n);
187   else
188     sprintf(buf,"0%1d",n);
189 }
190
191 static char *mydate(char buf[], int maxsize,gmx_bool bWiki)
192 {
193   const char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
194                          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
195   const char *day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
196   const char *num[] = { "01", "02", "03", "04", "05", "06","07", "08", "09" }; 
197   time_t now;
198   struct tm tm;
199   
200   time(&now);
201 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
202   /* Native windows */
203   localtime_s(&tm,&now);
204 #else
205   localtime_r(&now,&tm);
206 #endif
207
208   /* subtract one from maxsize, so we have room for \0. */
209   if (bWiki) {
210     char dd[8],mm[8],ss[8],hh[8],mn[8];
211     
212     mynum(dd,tm.tm_mday);
213     mynum(mm,tm.tm_mon);
214     mynum(ss,tm.tm_sec);
215     mynum(hh,tm.tm_hour);
216     mynum(mn,tm.tm_min);
217     sprintf(buf,"%4d-%2s-%2sT%2s:%2s:%2sZ",
218              tm.tm_year+1900,mm,dd,hh,mn,ss);
219   }
220   else
221     sprintf(buf,"%s %d %s %d",day[tm.tm_wday],tm.tm_mday,
222              mon[tm.tm_mon],tm.tm_year+1900);
223   
224   return buf;
225 }
226
227 /* Data structure for saved HTML links */
228 typedef struct t_linkdata {
229   int     nsr;
230   t_sandr *sr;
231 } t_linkdata;
232
233 static t_linkdata *init_linkdata()
234 {
235   t_linkdata *p;
236   snew(p,1);
237   p->sr=NULL;
238   p->nsr=0;
239
240   return p;
241 }
242
243 static void finish_linkdata(t_linkdata *p)
244 {
245   int i;
246   
247   for(i=0;i<p->nsr;i++) {
248     sfree(p->sr[i].search);    
249     sfree(p->sr[i].replace);
250   }
251   sfree(p->sr);
252   sfree(p);
253 }
254
255 static char *repall(const char *s,int nsr,const t_sandr_const sa[])
256 {
257   int  i;
258   char *buf1,*buf2;
259   
260   /* Copy input to a non-constant char buffer.
261    * buf1 is allocated here 
262    */
263   buf1=gmx_strdup(s); 
264   
265   for(i=0; (i<nsr); i++) {
266     /* Replace in buffer1, put result in buffer2.
267      * buf2 is allocated here.
268      */
269     buf2=replace(buf1,sa[i].search,sa[i].replace);
270     sfree(buf1);
271     buf1=buf2;
272   }
273   
274   return buf1;
275
276
277 static char *repallww(const char *s,int nsr,const t_sandr sa[])
278 {
279   int  i;
280   char *buf1,*buf2;
281
282   /* Copy input to a non-constant char buffer.
283    * buf1 is allocated here 
284    */
285   buf1=gmx_strdup(s); 
286   
287   for(i=0; (i<nsr); i++) {
288     /* Replace in buffer1, put result in buffer2.
289      * buf2 is allocated here.
290      */
291     buf2=replaceww(buf1,sa[i].search,sa[i].replace);
292     sfree(buf1);
293     buf1=buf2;
294   }
295   return buf1;
296 }
297
298 static char *html_xref(char *s,const char *program, t_linkdata *links,gmx_bool bWiki)
299 {
300   char   buf[256],**filestr;
301   int    i,j,n;
302   
303   if (links->sr == NULL) {
304     n=get_file("links.dat",&(filestr));
305     links->nsr=n;
306     snew(links->sr,n);
307     for(i=0,j=0; (i<n); i++) {
308       if (!program || (gmx_strcasecmp(program,filestr[i])  != 0)) {
309         links->sr[j].search=gmx_strdup(filestr[i]);
310         if (bWiki)
311           sprintf(buf,"[[%s]]",filestr[i]);
312         else
313           sprintf(buf,"<a href=\"%s.html\">%s</a>",filestr[i],filestr[i]);
314         links->sr[j].replace=gmx_strdup(buf);
315         j++;
316       }
317     }
318     links->nsr=j;
319     for(i=0;i<n;i++)
320       sfree(filestr[i]);
321     sfree(filestr);
322   }
323   return repallww(s,links->nsr,links->sr);
324 }
325
326 char *check_tex(const char *s)
327 {
328   return repall(s,NSRTEX,sandrTeX);
329 }
330
331 static char *check_nroff(const char *s)
332 {
333   return repall(s,NSRNROFF,sandrNROFF);
334 }
335
336 static char *check_wiki(const char *s,const char *program, t_linkdata *links)
337 {
338   char *buf;
339   
340   buf = repall(s,NSRWIKI,sandrWiki);
341   buf = html_xref(buf,program,links,TRUE);
342   
343   return buf;
344 }
345
346 static char *check_html(const char *s,const char *program, t_linkdata *links)
347 {
348   char *buf;
349   
350   buf = repall(s,NSRHTML,sandrHTML);
351   buf = html_xref(buf,program,links,FALSE);
352   
353   return buf;
354 }
355
356 #define NWR(s) check_wiki(s,program,links)
357 #define NSR(s) check_html(s,program,links)
358   
359 #define FLAG_SET(flag, mask) ((flag & mask) == mask)
360 char *fileopt(unsigned long flag,char buf[],int maxsize)
361 {
362   char tmp[256];
363   
364   if (FLAG_SET(flag, ffRW))
365     sprintf(tmp,"In/Out");
366   else if (FLAG_SET(flag, ffREAD))
367     sprintf(tmp,"Input");
368   else if (FLAG_SET(flag, ffWRITE))
369     sprintf(tmp,"Output");
370   else
371     sprintf(tmp,"Dunno");
372
373   if (FLAG_SET(flag, ffOPT)) {
374     strcat(tmp,", Opt");
375     if (FLAG_SET(flag, ffSET)) 
376       strcat(tmp,"!");
377     else
378       strcat(tmp,".");
379   }
380   if (FLAG_SET(flag, ffLIB))
381     strcat(tmp,", Lib.");
382   if (FLAG_SET(flag, ffMULT))
383     strcat(tmp,", Mult.");
384
385   sprintf(buf,"%s",tmp);
386   
387   return buf;
388 }
389
390 static void write_texman(FILE *out,const char *program,
391                          int nldesc,const char **desc,
392                          int nfile,t_filenm *fnm,
393                          int npargs,t_pargs *pa,
394                          int nbug,const char **bugs,
395                          t_linkdata *links)
396 {
397   int i;
398   char tmp[256];
399   
400   fprintf(out,"\\section{\\normindex{%s}}\\label{%s}\n\n",check_tex(program),check_tex(program));
401   
402   if (nldesc > 0)
403     for(i=0; (i<nldesc); i++) 
404       fprintf(out,"%s\n",check_tex(desc[i]));
405
406   if (nfile > 0) {
407     fprintf(out,"\\vspace{-2ex}\\begin{tabbing}\n");
408     fprintf(out,"\n{\\normalsize \\bf Files}\\nopagebreak\\\\\n");
409     fprintf(out,"{\\tt ~~~~~~~} \\= {\\tt ~~~~~~~~~~~~~~} \\= "
410             "~~~~~~~~~~~~~~~~~~~~~~ \\= \\nopagebreak\\kill\n");
411     for(i=0; (i<nfile); i++)
412       fprintf(out,"\\>{\\tt %s} \\'\\> {\\tt %s} \\' %s \\> "
413               "\\parbox[t]{0.55\\linewidth}{%s} \\\\\n",
414               check_tex(fnm[i].opt),check_tex(fnm[i].fns[0]),
415               check_tex(fileopt(fnm[i].flag,tmp,255)),
416               check_tex(ftp2desc(fnm[i].ftp)));
417     fprintf(out,"\\end{tabbing}\\vspace{-4ex}\n");
418   }
419   if (npargs > 0) {
420     fprintf(out,"\\vspace{-2ex}\\begin{tabbing}\n");
421     fprintf(out,"\n{\\normalsize \\bf Other options}\\nopagebreak\\\\\n");
422     fprintf(out,"{\\tt ~~~~~~~~~~} \\= vector \\= "
423             "{\\tt ~~~~~~~} \\= \\nopagebreak\\kill\n");
424     for(i=0; (i<npargs); i++) {
425       if (strlen(check_tex(pa_val(&(pa[i]),tmp,255))) <= 8)
426         fprintf(out,"\\> {\\tt %s} \\'\\> %s \\'\\> {\\tt %s} \\' "
427                 "\\parbox[t]{0.68\\linewidth}{%s}\\\\\n",
428                 check_tex(pa[i].option),argtp[pa[i].type],
429                 check_tex(pa_val(&(pa[i]),tmp,255)),
430                 check_tex(pa[i].desc));
431       else
432         fprintf(out,"\\> {\\tt %s} \\'\\> %s \\'\\>\\\\\n"
433                 "\\> \\'\\> \\'\\> {\\tt %s} \\' "
434                 "\\parbox[t]{0.7\\linewidth}{%s}\\\\\n",
435                 check_tex(pa[i].option),argtp[pa[i].type],
436                 check_tex(pa_val(&(pa[i]),tmp,255)),
437                 check_tex(pa[i].desc));
438     }
439     fprintf(out,"\\end{tabbing}\\vspace{-4ex}\n");
440   }
441   if (nbug > 0) {
442     fprintf(out,"\n");
443     fprintf(out,"\\begin{itemize}\n");
444     for(i=0; (i<nbug); i++)
445       fprintf(out,"\\item %s\n",check_tex(bugs[i]));
446     fprintf(out,"\\end{itemize}\n");
447   }
448 /*   fprintf(out,"\n\\newpage\n"); */
449 }
450
451 static void write_nroffman(FILE *out,
452                            const char *program,
453                            int nldesc,const char **desc,
454                            int nfile,t_filenm *fnm,
455                            int npargs,t_pargs *pa,
456                            int nbug,const char **bugs,
457                            t_linkdata *links)
458
459 {
460   int i;
461   char tmp[256];
462   
463   
464   fprintf(out,".TH %s 1 \"%s\" \"\" \"GROMACS suite, %s\"\n",program,mydate(tmp,255,FALSE),GromacsVersion());
465   fprintf(out,".SH NAME\n");
466   fprintf(out,"%s\n",program);
467   fprintf(out,".B %s\n",GromacsVersion());
468   
469   fprintf(out,".SH SYNOPSIS\n");
470   fprintf(out,"\\f3%s\\fP\n",program);
471
472   /* command line arguments */
473   if (nfile > 0) {
474     for(i=0; (i<nfile); i++)
475       fprintf(out,".BI \"%s\" \" %s \"\n",check_nroff(fnm[i].opt),
476               check_nroff(fnm[i].fns[0]));
477   }
478   if (npargs > 0) {
479     for(i=0; (i<npargs); i++)
480       if (pa[i].type == etBOOL)
481         fprintf(out,".BI \"\\-[no]%s\" \"\"\n",check_nroff(pa[i].option+1));
482       else
483         fprintf(out,".BI \"%s\" \" %s \"\n",check_nroff(pa[i].option),
484                 check_nroff(argtp[pa[i].type]));
485   }
486   
487   /* description */
488   if (nldesc > 0) {
489     fprintf(out,".SH DESCRIPTION\n");
490     for(i=0; (i<nldesc); i++) 
491       fprintf(out,"\\&%s\n",check_nroff(desc[i]));
492   }
493
494   /* FILES */
495   if (nfile > 0) {
496     fprintf(out,".SH FILES\n");
497     for(i=0; (i<nfile); i++)
498       fprintf(out,".BI \"%s\" \" %s\" \n.B %s\n %s \n\n",
499               check_nroff(fnm[i].opt),
500               check_nroff(fnm[i].fns[0]),
501               check_nroff(fileopt(fnm[i].flag,tmp,255)),
502               check_nroff(ftp2desc(fnm[i].ftp)));
503   }
504   
505   /* other options */
506   fprintf(out,".SH OTHER OPTIONS\n");
507   if ( npargs > 0 ) {
508     for(i=0; (i<npargs); i++) {
509       if (pa[i].type == etBOOL)
510         fprintf(out,".BI \"\\-[no]%s\"  \"%s\"\n %s\n\n",
511                 check_nroff(pa[i].option+1),
512                 check_nroff(pa_val(&(pa[i]),tmp,255)),
513                 check_nroff(pa[i].desc));
514       else
515         fprintf(out,".BI \"%s\"  \" %s\" \" %s\" \n %s\n\n",
516                 check_nroff(pa[i].option),
517                 check_nroff(argtp[pa[i].type]),
518                 check_nroff(pa_val(&(pa[i]),tmp,255)),
519                 check_nroff(pa[i].desc));
520     }
521   }
522
523   if (nbug > 0) {
524     fprintf(out,".SH KNOWN PROBLEMS\n");
525     for(i=0; (i<nbug); i++)
526       fprintf(out,"\\- %s\n\n",check_nroff(bugs[i]));
527   }
528
529   fprintf(out,".SH SEE ALSO\n.BR gromacs(7)\n\n");
530   fprintf(out,"More information about \\fBGROMACS\\fR is available at <\\fIhttp://www.gromacs.org/\\fR>.\n");
531
532 }
533
534 char *check_tty(const char *s)
535 {
536   return repall(s,NSRTTY,sandrTty);
537 }
538
539 void
540 print_tty_formatted(FILE *out, int nldesc, const char **desc,int indent,
541                     t_linkdata *links,const char *program,gmx_bool bWiki)
542 {
543   char *buf;
544   char *temp;
545   int buflen,i,j;
546
547   buflen = 80*nldesc;
548   snew(buf,buflen);
549   for(i=0; (i<nldesc); i++) {
550     if ((strlen(buf)>0) && 
551         (buf[strlen(buf)-1] !=' ') && (buf[strlen(buf)-1] !='\n'))
552       strcat(buf," ");
553     if (bWiki)
554       temp=NWR(desc[i]);
555     else
556       temp=check_tty(desc[i]);
557     if (strlen(buf) + strlen(temp) >= (size_t)(buflen-2)) {
558       buflen += strlen(temp);
559       srenew(buf,buflen);
560     }
561     strcat(buf,temp);
562     sfree(temp);
563   }
564   /* Make lines of at most 79 characters */
565   temp = wrap_lines(buf,78,indent,FALSE);
566   fprintf(out,"%s\n",temp);
567   sfree(temp);
568   sfree(buf);
569 }
570
571 static void write_ttyman(FILE *out,
572                          const char *program,
573                          int nldesc,const char **desc,
574                          int nfile,t_filenm *fnm,
575                          int npargs,t_pargs *pa,
576                          int nbug,const char **bugs,gmx_bool bHeader,
577                          t_linkdata *links)
578 {
579   int i;
580   char buf[256];
581   char *tmp;
582   
583   if (bHeader) {
584     fprintf(out,"%s\n\n",check_tty(program));
585     fprintf(out,"%s\n%s\n",GromacsVersion(),mydate(buf,255,FALSE));
586   }
587   if (nldesc > 0) {
588     fprintf(out,"DESCRIPTION\n-----------\n");
589     print_tty_formatted(out,nldesc,desc,0,links,program,FALSE);
590   }
591   if (nbug > 0) {
592     fprintf(out,"\n");
593     fprintf(out,"KNOWN PROBLEMS\n----------\n");
594     for(i=0; i<nbug; i++) {
595       snew(tmp,strlen(bugs[i])+3);
596       strcpy(tmp,"* ");
597       strcpy(tmp+2,check_tty(bugs[i]));
598       fprintf(out,"%s\n",wrap_lines(tmp,78,2,FALSE));
599       sfree(tmp);
600     }
601   }
602   if (nfile > 0) {
603     fprintf(out,"\n");
604     pr_fns(out,nfile,fnm);
605   }
606   if (npargs > 0) {
607     print_pargs(out,npargs,pa,FALSE);
608   }
609 }
610
611 static void pr_html_files(FILE *out,int nfile,t_filenm fnm[],
612                           const char *program,t_linkdata *links,gmx_bool bWiki)
613
614   int  i;
615   char link[10],tmp[255];
616   
617   if (bWiki)
618     fprintf(out," %-10s %-12s %-12s %-s\n"
619             " -----------------------------------------------------\n",
620             "Option","Filename","Type","Description");
621   else
622     fprintf(out,
623             "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>\n"
624             "<TR>"
625             "<TH>option</TH>"
626             "<TH>filename</TH>"
627             "<TH>type</TH>"
628             "<TH>description</TH>"
629             "</TR>\n");
630   
631   for(i=0; (i<nfile); i++) {
632     strcpy(link,ftp2ext(fnm[i].ftp));
633     if (strcmp(link,"???")==0)
634       strcpy(link,"files");
635     if (bWiki)
636       fprintf(out," %-10s %-16s %-12s %-s\n",
637               fnm[i].opt,
638               NWR(fnm[i].fns[0]),
639               fileopt(fnm[i].flag,tmp,255),
640               NWR(ftp2desc(fnm[i].ftp)));
641     else
642       fprintf(out,
643               "<TR>"
644               "<TD ALIGN=RIGHT> <b><tt>%s</tt></b> </TD>"
645               "<TD ALIGN=RIGHT> <tt><a href=\"%s.html\">%12s</a></tt> </TD>"
646               "<TD> %s </TD>"
647               "<TD> %s </TD>"
648               "</TR>\n",
649               fnm[i].opt,link,fnm[i].fns[0],fileopt(fnm[i].flag,tmp,255),
650               NSR(ftp2desc(fnm[i].ftp)));
651   }
652   if (!bWiki)
653     fprintf(out,"</TABLE>\n");
654 }
655
656 static void write_wikiman(FILE *out,
657                           const char *program,
658                           int nldesc,const char **desc,
659                           int nfile,t_filenm *fnm,
660                           int npargs,t_pargs *pa,
661                           int nbug,const char **bugs,gmx_bool bHeader,
662                           t_linkdata *links)
663 {
664   int i;
665   char buf[256],link[10];
666   char *tmp,*tmp2;
667   fprintf(out,"<page>\n<title>Manual:%s_%s</title>\n",program,
668           VERSION);
669   fprintf(out,"<revision>\n");
670   fprintf(out,"<timestamp>%s</timestamp>\n",mydate(buf,255,TRUE));
671   fprintf(out,"<text xml:space=\"preserve\">\n");
672   if (nldesc > 0) {
673     fprintf(out,"== Description ==\n");
674     print_tty_formatted(out,nldesc,desc,0,links,program,TRUE);
675     fprintf(out,"\n");
676   }
677   if (nbug > 0) {
678     fprintf(out,"== Known Problems ==\n");
679     for(i=0; i<nbug; i++) {
680       snew(tmp,strlen(bugs[i])+3);
681       strcpy(tmp,"* ");
682       strcpy(tmp+2,bugs[i]);
683       fprintf(out,"%s\n",NWR(tmp));
684       sfree(tmp);
685     }
686   }
687   if (nfile > 0) {
688     fprintf(out,"\n== Files ==\n");
689     pr_html_files(out,nfile,fnm,program,links,TRUE);
690   }
691   if (npargs > 0) {
692     fprintf(out,"\n== Options ==\n");
693     fprintf(out," %-12s %-6s %-6s  %-s\n",
694             "Option","Type","Value","Description");
695     fprintf(out," ------------------------------------------------------\n");
696     for(i=0; (i<npargs); i++) {
697       tmp = NWR(pargs_print_line(&pa[i],TRUE));
698       fprintf(out,"%s",tmp);
699       sfree(tmp);
700     }
701   }
702   fprintf(out,"[[category:Manual_Pages_%s|%s]]\n",VERSION,program);
703   fprintf(out,"</text>\n");
704   fprintf(out,"</revision>\n");
705   fprintf(out,"</page>\n\n");
706 }
707
708 static void write_htmlman(FILE *out,
709                           const char *program,
710                           int nldesc,const char **desc,
711                           int nfile,t_filenm *fnm,
712                           int npargs,t_pargs *pa,
713                           int nbug,const char **bugs,
714                           t_linkdata *links)
715 {
716   int i;
717   char link[10],tmp[255];
718   
719   fprintf(out,"<HTML>\n<HEAD>\n<TITLE>%s</TITLE>\n",program);
720   fprintf(out,"<LINK rel=stylesheet href=\"style.css\" type=\"text/css\">\n");
721   fprintf(out,"<BODY text=\"#000000\" bgcolor=\"#FFFFFF\" link=\"#0000FF\" vlink=\"#990000\" alink=\"#FF0000\">\n");
722   fprintf(out,"<TABLE WIDTH=\"98%%\" NOBORDER >\n<TR><TD WIDTH=400>\n");
723   fprintf(out,"<TABLE WIDTH=400 NOBORDER>\n<TD WIDTH=116>\n");
724   fprintf(out,"<a href=\"http://www.gromacs.org/\">"
725           "<img SRC=\"../images/gmxlogo_small.png\""
726           "BORDER=0 </a></td>\n");
727   fprintf(out,"<td ALIGN=LEFT VALIGN=TOP WIDTH=280>"
728           "<br><h2>%s</h2>",program);
729   fprintf(out,"<font size=-1><A HREF=\"../online.html\">Main Table of Contents</A></font><br>");
730   fprintf(out,"<br></td>\n</TABLE></TD><TD WIDTH=\"*\" ALIGN=RIGHT VALIGN=BOTTOM><p><B>%s<br>\n",GromacsVersion());
731   fprintf(out,"%s</B></td></tr></TABLE>\n<HR>\n",mydate(tmp,255,FALSE));
732   
733   if (nldesc > 0) {
734     fprintf(out,"<H3>Description</H3>\n<p>\n");
735     for(i=0; (i<nldesc); i++) 
736       fprintf(out,"%s\n",NSR(desc[i]));
737   }
738   if (nfile > 0) {
739     fprintf(out,"<P>\n");
740     fprintf(out,"<H3>Files</H3>\n");
741     pr_html_files(out,nfile,fnm,program,links,FALSE);
742   }
743   if (npargs > 0) {
744     fprintf(out,"<P>\n");
745     fprintf(out,"<H3>Other options</H3>\n");
746     fprintf(out,
747             "<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=2>\n"
748             "<TR>"
749             "<TH>option</TH>"
750             "<TH>type</TH>"
751             "<TH>default</TH>"
752             "<TH>description</TH>"
753             "</TR>\n");
754     for(i=0; (i<npargs); i++)
755       fprintf(out,
756               "<TR>"
757               "<TD ALIGN=RIGHT> <b><tt>%s%s</tt></b> </TD>"
758               "<TD ALIGN=RIGHT> %s </TD>"
759               "<TD ALIGN=RIGHT> <tt>%s</tt> </TD>"
760               "<TD> %s </TD>"
761               "</TD>\n",
762               (pa[i].type == etBOOL)?"-[no]":"-",pa[i].option+1,
763               argtp[pa[i].type],pa_val(&(pa[i]),tmp,255),NSR(pa[i].desc));
764     fprintf(out,"</TABLE>\n");
765   }
766   if (nbug > 0) {
767     fprintf(out,"<P>\n");
768     fprintf(out,"<H3>Known problems</H3>\n");
769     fprintf(out,"<UL>\n");
770     for(i=0; (i<nbug); i++)
771       fprintf(out,"<LI>%s\n",NSR(bugs[i]));
772     fprintf(out,"</UL>\n");
773   }
774   fprintf(out,"<P>\n");
775   fprintf(out,"<hr>\n<div ALIGN=RIGHT>\n");
776   fprintf(out,"<font size=\"-1\"><a href=\"http://www.gromacs.org\">"
777           "http://www.gromacs.org</a></font><br>\n");
778   fprintf(out,"<font size=\"-1\"><a href=\"mailto:gromacs@gromacs.org\">"
779           "gromacs@gromacs.org</a></font><br>\n");
780   fprintf(out,"</div>\n");
781   fprintf(out,"</BODY>\n");
782 }
783
784 char *check_xml(const char *s,const char *program,t_linkdata *links)
785 {
786   char *buf;
787   
788   buf=repall(s,NSRXML,sandrXML);
789   buf=html_xref(buf,program,links,FALSE);       /* the same in html and xml */
790   
791   return buf;
792 }
793
794 static void write_xmlman(FILE *out,
795                          const char *program,
796                          int nldesc,const char **desc,
797                          int nfile,t_filenm *fnm,
798                          int npargs,t_pargs *pa,
799                          int nbug,const char **bugs,
800                          t_linkdata *links)
801 {
802   int i;
803   char link[10],buf[256],opt[10];
804
805 #define NSR2(s) check_xml(s,program,links)
806 #define FLAG(w,f) (((w) & (f))==(f)) 
807
808   fprintf(out,"<gromacs-manual version=\"%s\" date=\"%s\" www=\"http://www.gromacs.org\">\n",GromacsVersion(),mydate(buf,255,FALSE));
809   /* fprintf(out,"<LINK rel=stylesheet href=\"style.css\" type=\"text/css\">\n"); */
810
811   fprintf(out,"<program name=\"%s\">",program);  
812   if (nldesc > 0) {
813     fprintf(out,"\n<description>\n<par>\n");
814     for(i=0; (i<nldesc); i++) 
815       fprintf(out,"%s\n",NSR2(desc[i]));
816   }
817   fprintf(out,"</par>\n</description>\n");
818
819   if (nfile > 0) {
820     fprintf(out,"\n<files>\n");
821     for(i=0; (i<nfile); i++) {
822       strcpy(link,ftp2ext(fnm[i].ftp));
823       if (strcmp(link,"???")==0)
824         strcpy(link,"files");
825         if (fnm[i].opt[0]=='-') strcpy(opt,fnm[i].opt+1);
826         else strcpy(opt,fnm[i].opt);
827       fprintf(out,
828               "<file type=\"%s\" typeid=\"%d\">\n"
829               "\t<flags read=\"%d\" write=\"%d\" optional=\"%d\"/>\n"
830               "\t<option>%s</option>\n"
831               "\t<default-name link=\"%s.html\">%s</default-name>\n"
832               "\t<description>%s</description>\n"
833               "</file>\n",
834               ftp2defnm(fnm[i].ftp),    /* from gmxlib/filenm.c */
835               fnm[i].ftp,
836               FLAG(fnm[i].flag,ffREAD), FLAG(fnm[i].flag,ffWRITE), FLAG(fnm[i].flag,ffOPT), 
837               opt,link,fnm[i].fn,/*fileopt(fnm[i].flag),*/
838               NSR(ftp2desc(fnm[i].ftp)));
839     }
840     fprintf(out,"</files>\n");
841   }
842
843   if (npargs > 0) {
844     fprintf(out,"\n<options>\n");
845     for(i=0; (i<npargs); i++)
846       fprintf(out,
847               "<option type=\"%s\" hidden=\"%d\">\n"
848               "\t<name >%s</name>\n"
849               "\t<default-value>%s</default-value>\n"
850               "\t<description>%s</description>\n"
851               "</option>\n",
852               argtp[pa[i].type], is_hidden(&pa[i]),
853               pa[i].option+1,                  /* +1 - with no trailing '-' */
854               pa_val(&(pa[i]),buf,255),pa[i].desc); /*argtp[pa[i].type],*/
855     fprintf(out,"</options>\n");
856   }
857
858   if (nbug > 0) {
859     fprintf(out,"\n<bugs>\n");
860     for(i=0; (i<nbug); i++)
861       fprintf(out,"\t<bug>%s</bug>\n",NSR(bugs[i]));
862     fprintf(out,"</bugs>\n");
863   }
864   fprintf(out,"\n</program>\n</gromacs-manual>\n");
865 #undef FLAG  
866 }
867
868 static void pr_opts(FILE *fp, 
869                     int nfile,  t_filenm *fnm, 
870                     int npargs, t_pargs pa[], int shell)
871 {
872   int i;
873   
874   switch (shell) {
875   case eshellCSH:
876     fprintf(fp," \"c/-/(");
877     for (i=0; i<nfile; i++)
878       fprintf(fp," %s",fnm[i].opt+1);
879     for (i=0; i<npargs; i++)
880       if ( (pa[i].type==etBOOL) && *(pa[i].u.b) )
881         fprintf(fp," no%s",pa[i].option+1);
882       else
883         fprintf(fp," %s",pa[i].option+1);
884     fprintf(fp,")/\"");
885     break;
886   case eshellBASH:
887     fprintf(fp,"if (( $COMP_CWORD <= 1 )) || [[ $c == -* ]]; then COMPREPLY=( $(compgen  -W '");
888     for (i=0; i<nfile; i++)
889       fprintf(fp," -%s",fnm[i].opt+1);
890     for (i=0; i<npargs; i++)
891       if ( (pa[i].type==etBOOL) && *(pa[i].u.b) )
892         fprintf(fp," -no%s",pa[i].option+1);
893       else
894         fprintf(fp," -%s",pa[i].option+1);
895     fprintf(fp,"' -- $c)); return 0; fi\n");
896     break;
897   case eshellZSH:
898     fprintf(fp," -x 's[-]' -s \"");
899     for (i=0; i<nfile; i++)
900       fprintf(fp," %s",fnm[i].opt+1);
901     for (i=0; i<npargs; i++)
902       if ( (pa[i].type==etBOOL) && *(pa[i].u.b) )
903         fprintf(fp," no%s",pa[i].option+1);
904       else
905         fprintf(fp," %s",pa[i].option+1);
906     fprintf(fp,"\" ");
907     break;
908   }
909 }
910
911 static void write_cshcompl(FILE *out,
912                            int nfile,  t_filenm *fnm,
913                            int npargs, t_pargs *pa)
914 {
915   fprintf(out,"complete %s",ShortProgram());
916   pr_enums(out,npargs,pa,eshellCSH);
917   pr_fopts(out,nfile,fnm,eshellCSH);
918   pr_opts(out,nfile,fnm,npargs,pa,eshellCSH);
919   fprintf(out,"\n");
920 }
921
922 static void write_zshcompl(FILE *out,
923                            int nfile,  t_filenm *fnm,
924                            int npargs, t_pargs *pa)
925 {
926   fprintf(out,"compctl ");
927
928   /* start with options, since they are always present */
929   pr_opts(out,nfile,fnm,npargs,pa,eshellZSH);
930   pr_enums(out,npargs,pa,eshellZSH);
931   pr_fopts(out,nfile,fnm,eshellZSH);
932   fprintf(out,"-- %s\n",ShortProgram());
933 }
934
935 static void write_bashcompl(FILE *out,
936                             int nfile,  t_filenm *fnm,
937                             int npargs, t_pargs *pa)
938 {
939   /* Advanced bash completions are handled by shell functions.
940    * p and c hold the previous and current word on the command line.
941    * We need to use extended globbing, so write it in each completion file */
942   fprintf(out,"shopt -s extglob\n");
943   fprintf(out,"_%s_compl() {\nlocal p c\n",ShortProgram());
944   fprintf(out,"COMPREPLY=() c=${COMP_WORDS[COMP_CWORD]} p=${COMP_WORDS[COMP_CWORD-1]}\n");
945   pr_opts(out,nfile,fnm,npargs,pa,eshellBASH);
946   fprintf(out,"case \"$p\" in\n");
947   
948   pr_enums(out,npargs,pa,eshellBASH);
949   pr_fopts(out,nfile,fnm,eshellBASH);
950   fprintf(out,"esac }\ncomplete -F _%s_compl %s\n",ShortProgram(),ShortProgram());
951 }
952
953 static void write_py(FILE *out,const char *program,
954                      int nldesc,const char **desc,
955                      int nfile,t_filenm *fnm,
956                      int npargs,t_pargs *pa,
957                      int nbug,const char **bugs,
958                      t_linkdata *links)
959 {
960   gmx_bool bHidden;
961   const char *cls = program;
962   char *tmp;
963   int  i,j;
964
965   /* Header stuff */  
966   fprintf(out,"#!/usr/bin/python\n\nfrom GmxDialog import *\n\n");
967   
968   /* Class definition */
969   fprintf(out,"class %s:\n",cls);
970   fprintf(out,"    def __init__(self,tk):\n");
971   
972   /* Help text */
973   fprintf(out,"        %s_help = \"\"\"\n",cls);
974   fprintf(out,"        DESCRIPTION\n");
975   print_tty_formatted(out,nldesc,desc,8,links,program,FALSE);
976   if (nbug > 0) {
977     fprintf(out,"\n        BUGS and PROBLEMS\n");
978     for(i=0; i<nbug; i++) {
979       snew(tmp,strlen(bugs[i])+3);
980       strcpy(tmp,"* ");
981       strcpy(tmp+2,check_tty(bugs[i]));
982       fprintf(out,"%s\n",wrap_lines(tmp,78,10,TRUE));
983       sfree(tmp);
984     }
985   }
986   fprintf(out,"        \"\"\"\n\n        # Command line options\n");
987   /* File options */
988   fprintf(out,"        flags = []\n");
989   for(i=0; (i<nfile); i++) 
990     fprintf(out,"        flags.append(pca_file('%s',\"%s\",0,%d))\n",
991             ftp2ext_generic(fnm[i].ftp),fnm[i].opt ? fnm[i].opt : "k",
992             is_optional(&(fnm[i])));
993             
994             
995   /* Other options */
996   for(i=0; (i<npargs); i++) {
997     switch(pa[i].type) {
998     case etINT:
999       fprintf(out,"        flags.append(pca_int(\"%s\",\"%s\",%d,%d))\n",
1000               pa[i].option,pa[i].desc,*pa[i].u.i,is_hidden(&(pa[i])));
1001       break;
1002     case etREAL:
1003     case etTIME:
1004       fprintf(out,"        flags.append(pca_float(\"%s\",\"%s\",%f,%d))\n",
1005               pa[i].option,pa[i].desc,*pa[i].u.r,is_hidden(&(pa[i])));
1006       break;
1007     case etSTR:
1008     case etBOOL:
1009       fprintf(out,"        flags.append(pca_gmx_bool(\"%s\",\"%s\",%d,%d))\n",
1010               pa[i].option,pa[i].desc,*pa[i].u.b,is_hidden(&(pa[i])));
1011       break;
1012     case etRVEC:
1013       fprintf(stderr,"Sorry, no rvecs yet...\n");
1014       break;
1015     case etENUM:
1016       fprintf(out,"        flags.append(pca_enum(\"%s\",\"%s\",\n",
1017               pa[i].option,pa[i].desc);
1018       fprintf(out,"        ['%s'",pa[i].u.c[1]);
1019       for(j=2; (pa[i].u.c[j] != NULL); j++)
1020         fprintf(out,",'%s'",pa[i].u.c[j]);
1021       fprintf(out,"],%d))\n",is_hidden(&(pa[i])));
1022     default:
1023       break;
1024     }
1025   }
1026     
1027   /* Make the dialog box */
1028   fprintf(out,"        gmxd = gmx_dialog(tk,\"%s\",flags,%s_help)\n\n",
1029           cls,cls);
1030           
1031   /* Main loop */
1032   fprintf(out,"#####################################################\n");
1033   fprintf(out,"tk     = Tk()\n");
1034   fprintf(out,"my%s = %s(tk)\n",cls,cls);
1035   fprintf(out,"tk.mainloop()\n");
1036 }
1037
1038 void write_man(FILE *out,const char *mantp,
1039                const char *program,
1040                int nldesc,const char **desc,
1041                int nfile,t_filenm *fnm,
1042                int npargs,t_pargs *pa,
1043                int nbug,const char **bugs,
1044                gmx_bool bHidden)
1045 {
1046   const char *pr;
1047   int     i,npar;
1048   t_pargs *par;
1049  
1050   t_linkdata *links;
1051   
1052   links=init_linkdata();
1053   
1054   /* Don't write hidden options to completions, it just
1055    * makes the options more complicated for normal users
1056    */
1057
1058   if (bHidden) {
1059     npar=npargs;
1060     par=pa;
1061   }
1062   else {
1063     snew(par,npargs);
1064     npar=0;
1065     for(i=0;i<npargs;i++)
1066       if (!is_hidden(&pa[i])) {
1067         par[npar]=pa[i];
1068         npar++;
1069       }
1070   }
1071   
1072   if ((pr=strrchr(program,DIR_SEPARATOR)) == NULL)
1073     pr=program;
1074   else
1075     pr+=1;
1076   if (strcmp(mantp,"tex")==0)
1077     write_texman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,links);
1078   if (strcmp(mantp,"nroff")==0)
1079     write_nroffman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,links);
1080   if (strcmp(mantp,"ascii")==0)
1081     write_ttyman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,TRUE,links);
1082   if (strcmp(mantp,"wiki")==0)
1083     write_wikiman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,TRUE,links);
1084   if (strcmp(mantp,"help")==0)
1085     write_ttyman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,FALSE,links);
1086   if (strcmp(mantp,"html")==0)
1087     write_htmlman(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,links);
1088   if (strcmp(mantp,"py")==0)
1089     write_py(out,pr,nldesc,desc,nfile,fnm,npar,par,nbug,bugs,links);
1090   if (strcmp(mantp,"xml")==0)
1091     write_xmlman(out,pr,nldesc,desc,nfile,fnm,npargs,pa,nbug,bugs,links);       
1092   if (strcmp(mantp,"completion-zsh")==0)
1093     write_zshcompl(out,nfile,fnm,npar,par);
1094   if (strcmp(mantp,"completion-bash")==0)
1095     write_bashcompl(out,nfile,fnm,npar,par);
1096   if (strcmp(mantp,"completion-csh")==0)
1097     write_cshcompl(out,nfile,fnm,npar,par);
1098
1099   if (!bHidden)
1100     sfree(par);
1101
1102   finish_linkdata(links);
1103 }
1104