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