source: git/Singular/fehelp.cc @ 06929a

spielwiese
Last change on this file since 06929a was 06929a, checked in by Hans Schönemann <hannes@…>, 21 years ago
*hannes: help.cnf git-svn-id: file:///usr/local/Singular/svn/trunk@6687 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 28.1 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: help system
6*/
7
8#include <string.h>
9#include <unistd.h>
10#include <stdio.h>
11#include <stddef.h>
12#include <stdlib.h>
13#include <time.h>
14
15#include "mod2.h"
16#include <mylimits.h>
17#include "tok.h"
18#include "omalloc.h"
19#include "febase.h"
20#include "ipid.h"
21#include "ipshell.h"
22#include "libparse.h"
23#include "feOpt.h"
24#include "dError.h"
25
26/*****************************************************************
27 *
28 * Declarations: Data  structures
29 *
30 *****************************************************************/
31#define MAX_HE_ENTRY_LENGTH 60
32typedef struct
33{
34  char key[MAX_HE_ENTRY_LENGTH];
35  char node[MAX_HE_ENTRY_LENGTH];
36  char url[MAX_HE_ENTRY_LENGTH];
37  long  chksum;
38} heEntry_s;
39typedef  heEntry_s * heEntry;
40
41typedef void (*heBrowserHelpProc)(heEntry hentry, int br);
42typedef BOOLEAN (*heBrowserInitProc)(int warn, int br);
43
44typedef struct
45{
46  char* browser;
47  heBrowserInitProc init_proc;
48  heBrowserHelpProc help_proc;
49  char* required;
50  char* action;
51} heBrowser_s;
52typedef heBrowser_s * heBrowser;
53
54/*****************************************************************
55 *
56 * Declarations: Local functions
57 *
58 *****************************************************************/
59static char* strclean(char* str);
60static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry);
61static int heReKey2Entry (char* filename, char* key, heEntry hentry);
62static BOOLEAN strmatch(char* s, char* re);
63static BOOLEAN heOnlineHelp(char* s);
64static void heBrowserHelp(heEntry hentry);
65static long heKeyChksum(char* key);
66
67// browser functions
68static BOOLEAN heGenInit(int,int);    static void heGenHelp(heEntry hentry,int);
69                                      static void heBuiltinHelp(heEntry hentry,int);
70static BOOLEAN heDummyInit(int,int);   static void heDummyHelp(heEntry hentry,int);
71static BOOLEAN heEmacsInit(int,int);   static void heEmacsHelp(heEntry hentry,int);
72
73#ifdef ix86_Win
74static void heHtmlHelp(heEntry hentry,int);
75static void heWinHelp(heEntry hentry,int);
76#include "sing_win.h"
77#endif
78
79static heBrowser heCurrentHelpBrowser = NULL;
80static int heCurrentHelpBrowserIndex= -1;
81
82
83/*****************************************************************
84 *
85 * Definition: available help browsers
86 *
87 *****************************************************************/
88// order is improtant -- first possible help is choosen
89#if 1
90static heBrowser_s *heHelpBrowsers=NULL;
91#else
92static heBrowser_s heHelpBrowsers[] =
93{
94#ifdef ix86_Win
95//  { "html",     heDummyInit,    heHtmlHelp, NULL, NULL},
96//  { "winhlp",   heDummyInit,    heWinHelp, NULL, NULL},
97#endif
98  { "mozilla",  heGenInit,      heGenHelp, "xDhE:mozilla:", "(mozilla -remote \"openURL(%h)\")||(mozilla %h)"},
99  { "netscape", heGenInit,      heGenHelp, "xDhE:netscape:", "(netscape -remote \"openURL(%h)\")||(netscape %h)"},
100  { "tkinfo",   heGenInit,      heGenHelp, "xDiE:tkinfo:", "tkinfo '(%i)%n' &"},
101  { "xinfo",    heGenInit,      heGenHelp, "xDiE:xterm:E:info:", "xterm -e info -f %i --node='%n' &"},
102  { "mac",      heGenInit,      heGenHelp,  "xhE:open:","open %h" },
103  { "machtml",  heGenInit,      heGenHelp,  "xE:open:","open %H" },
104  { "info",     heGenInit,      heGenHelp, "xiE:info:", "info -f %i --node='%n' &"},
105  { "builtin",  heGenInit,      heBuiltinHelp, "i", NULL},
106  { "dummy",    heDummyInit,    heDummyHelp, NULL, NULL},
107  { "emacs",    heEmacsInit,    heEmacsHelp, NULL, NULL},
108  { NULL, NULL, NULL, NULL, NULL} // must be the last record
109};
110#endif
111
112/*****************************************************************
113 *
114 * Implementation: public function
115 *
116 *****************************************************************/
117void feHelp(char *str)
118{
119  str = strclean(str);
120  if (str == NULL) {heBrowserHelp(NULL); return;}
121
122  if (strlen(str) > MAX_HE_ENTRY_LENGTH - 2)  // need room for extra **
123    str[MAX_HE_ENTRY_LENGTH - 3] = '\0';
124
125  BOOLEAN key_is_regexp = (strchr(str, '*') != NULL);
126  heEntry_s hentry;
127  char* idxfile = feResource('x' /*"IdxFile"*/);
128
129  // Try exact match of help string with key in index
130  if (!key_is_regexp && idxfile != NULL && heKey2Entry(idxfile, str, &hentry))
131  {
132    heBrowserHelp(&hentry);
133    return;
134  }
135
136  // try proc help and library help
137  if (! key_is_regexp && heOnlineHelp(str)) return;
138
139  // Try to match approximately with key in index file
140  if (idxfile != NULL)
141  {
142    char* matches = StringSetS("");
143    int found = heReKey2Entry(idxfile, str, &hentry);
144
145    // Try to match with str*
146    if (found == 0)
147    {
148      char mkey[MAX_HE_ENTRY_LENGTH];
149      strcpy(mkey, str);
150      strcat(mkey, "*");
151      found = heReKey2Entry(idxfile, mkey, &hentry);
152      // Try to match with *str*
153      if (found == 0)
154      {
155        mkey[0] = '*';
156        strcpy(mkey + 1, str);
157        strcat(mkey, "*");
158        found = heReKey2Entry(idxfile, mkey, &hentry);
159      }
160
161      // Print warning and return if nothing found
162      if (found == 0)
163      {
164        Warn("No help for topic '%s' (not even for '*%s*')", str, str);
165        WarnS("Try '?;'       for general help");
166        WarnS("or  '?Index;'  for all available help topics.");
167        return;
168      }
169    }
170
171    // do help if unique match was found
172    if (found == 1)
173    {
174      heBrowserHelp(&hentry);
175      return;
176    }
177    // Print warning about multiple matches and return
178    if (key_is_regexp)
179      Warn("No unique help for '%s'", str);
180    else
181      Warn("No help for topic '%s'", str);
182    Warn("Try one of");
183    PrintS(matches);
184    PrintS("\n");
185    return;
186  }
187
188  // no idx file, let Browsers deal with it, if they can
189  strcpy(hentry.key, str);
190  *hentry.node = '\0';
191  *hentry.url = '\0';
192  hentry.chksum = 0;
193  heBrowserHelp(&hentry);
194}
195static void feBrowserFile()
196{
197  FILE *f=feFopen("help.cnf","r",NULL,TRUE);
198  int br=0;
199  if (f!=NULL)
200  {
201    char buf[512];
202    while (fgets( buf, sizeof(buf), f))
203    {
204      if ((buf[0]!='#') && (buf[0]>' ')) br++;
205    }
206    fseek(f,0,SEEK_SET);
207    // for the 4(!) default browsers
208    heHelpBrowsers=(heBrowser_s*)omAlloc0((br+4)*sizeof(heBrowser_s));
209    br=0;
210    while (fgets( buf, sizeof(buf), f))
211    {
212      if ((buf[0]!='#') && (buf[0]>' '))
213      {
214        char *name=strtok(buf,"!");
215        char *req=strtok(NULL,"!");
216        char *cmd=strtok(NULL,"!");
217        while ((cmd[0]!='\0') && (cmd[strlen(cmd)-1]<=' '))
218          cmd[strlen(cmd)-1]='\0';
219        //Print("name %d >>%s<<\n\treq:>>%s<<\n\tcmd:>>%s<<\n",br,name,req,cmd);
220        heHelpBrowsers[br].browser=(char *)omStrDup(name);
221        heHelpBrowsers[br].init_proc=heGenInit;
222        heHelpBrowsers[br].help_proc=heGenHelp;
223        heHelpBrowsers[br].required=omStrDup(req);
224        heHelpBrowsers[br].action=omStrDup(cmd);
225        br++;
226      }
227    }
228    fclose(f);
229  }
230  else
231  {
232    // for the 4(!) default browsers
233    heHelpBrowsers=(heBrowser_s*)omAlloc0(4*sizeof(heBrowser_s));
234  }
235  heHelpBrowsers[br].browser="builtin";
236  heHelpBrowsers[br].init_proc=heGenInit;
237  heHelpBrowsers[br].help_proc=heBuiltinHelp;
238  heHelpBrowsers[br].required="i";
239  //heHelpBrowsers[br].action=NULL;
240  br++;
241  heHelpBrowsers[br].browser="dummy";
242  heHelpBrowsers[br].init_proc=heDummyInit;
243  heHelpBrowsers[br].help_proc=heDummyHelp;
244  //heHelpBrowsers[br].required=NULL;
245  //heHelpBrowsers[br].action=NULL;
246  br++;
247  heHelpBrowsers[br].browser="emacs";
248  heHelpBrowsers[br].init_proc=heEmacsInit;
249  heHelpBrowsers[br].help_proc=heEmacsHelp;
250  //heHelpBrowsers[br].required=NULL;
251  //heHelpBrowsers[br].action=NULL;
252  //br++;
253  //heHelpBrowsers[br].browser=NULL;
254  //heHelpBrowsers[br].init_proc=NULL;
255  //heHelpBrowsers[br].help_proc=NULL;
256  //heHelpBrowsers[br].required=NULL;
257  //heHelpBrowsers[br].action=NULL;
258}
259
260char* feHelpBrowser(char* which, int warn)
261{
262  int i = 0;
263
264  // if no argument, choose first available help browser
265  if (heHelpBrowsers==NULL) feBrowserFile();
266  if (which == NULL || *which == '\0')
267  {
268    // return, if already set
269    if (heCurrentHelpBrowser != NULL)
270      return heCurrentHelpBrowser->browser;
271
272    // First, try emacs, if emacs-option is set
273    // Under Win, always use html
274#ifndef ix86_Win
275    if (feOptValue(FE_OPT_EMACS) != NULL)
276    {
277      while (heHelpBrowsers[i].browser != NULL)
278      {
279        if (strcmp(heHelpBrowsers[i].browser, "emacs") == 0 &&
280            (heHelpBrowsers[i].init_proc(0,i)))
281        {
282          heCurrentHelpBrowser = &(heHelpBrowsers[i]);
283          heCurrentHelpBrowserIndex=i;
284          goto Finish;
285        }
286        i++;
287      }
288      i=0;
289    }
290#endif
291    while (heHelpBrowsers[i].browser != NULL)
292    {
293      if (heHelpBrowsers[i].init_proc(0,i))
294      {
295        heCurrentHelpBrowser = &(heHelpBrowsers[i]);
296        heCurrentHelpBrowserIndex=i;
297        goto Finish;
298      }
299      i++;
300    }
301    // should never get here
302    dReportBug("should never get here");
303  }
304
305  // with argument, find matching help browser
306  while (heHelpBrowsers[i].browser != NULL &&
307         strcmp(heHelpBrowsers[i].browser, which) != 0)
308  {i++;}
309
310  if (heHelpBrowsers[i].browser == NULL)
311  {
312    if (warn) Warn("No help browser '%s' available.", which);
313  }
314  else
315  {
316    // see whether we can init it
317    if (heHelpBrowsers[i].init_proc(warn,i))
318    {
319      heCurrentHelpBrowser = &(heHelpBrowsers[i]);
320      heCurrentHelpBrowserIndex=i;
321      goto Finish;
322    }
323  }
324
325  // something went wrong
326  if (heCurrentHelpBrowser == NULL)
327  {
328    feHelpBrowser();
329    assume(heCurrentHelpBrowser != NULL);
330    if (warn)
331      Warn("Setting help browser to '%s'.", heCurrentHelpBrowser->browser);
332    return heCurrentHelpBrowser->browser;
333  }
334  else
335  {
336    // or, leave as is
337    if (warn)
338      Warn("Help browser stays at '%s'.",  heCurrentHelpBrowser->browser);
339    return heCurrentHelpBrowser->browser;
340  }
341
342  Finish:
343  // update value of Browser Option
344  if (feOptSpec[FE_OPT_BROWSER].value == NULL ||
345      strcmp((char*) feOptSpec[FE_OPT_BROWSER].value,
346             heCurrentHelpBrowser->browser) != 0)
347  {
348    omfree(feOptSpec[FE_OPT_BROWSER].value);
349    feOptSpec[FE_OPT_BROWSER].value
350     = (void*) omStrDup(heCurrentHelpBrowser->browser);
351  }
352  return heCurrentHelpBrowser->browser;
353}
354
355void  feStringAppendBrowsers(int warn)
356{
357  int i;
358  StringAppendS("Available HelpBrowsers: ");
359
360  i = 0;
361  if (heHelpBrowsers==NULL) feBrowserFile();
362  while (heHelpBrowsers[i].browser != NULL)
363  {
364    if (heHelpBrowsers[i].init_proc(warn,i))
365      StringAppend("%s, ", heHelpBrowsers[i].browser);
366    i++;
367  }
368  StringAppend("\nCurrent HelpBrowser: %s ", feHelpBrowser());
369}
370
371
372/*****************************************************************
373 *
374 * Implementation: local function
375 *
376 *****************************************************************/
377// Remove whitspaces from beginning and end, return NULL if only whitespaces
378static char* strclean(char* str)
379{
380  if (str == NULL) return NULL;
381  char *s=str;
382  while (*s <= ' ' && *s != '\0') s++;
383  if (*s == '\0') return NULL;
384  char *ss=s;
385  while (*ss!='\0') ss++;
386  ss--;
387  while (*ss <= ' ' && *ss != '\0')
388  {
389    *ss='\0';
390    ss--;
391  }
392  if (*ss == '\0') return NULL;
393  return s;
394}
395
396// Finds help entry for key:
397// returns filled-in hentry and TRUE, on success
398// FALSE, on failure
399// Assumes that lines of idx file have the following form
400// key\tnode\turl\tchksum\n (chksum ma be empty, then it is set to -1)
401// and that lines are sorted alpahbetically w.r.t. index entries
402static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry)
403{
404  FILE* fd;
405  char c, k;
406  int kl, i;
407  *(hentry->key) = '\0';
408  *(hentry->url) = '\0';
409  *(hentry->node) = '\0';
410  hentry->chksum = 0;
411  if (filename == NULL || key == NULL)  return FALSE;
412  fd = fopen(filename, "r");
413  if (fd == NULL) return FALSE;
414  kl = strlen(key);
415
416  k = key[0];
417  i = 0;
418  while ((c = getc(fd)) != EOF)
419  {
420    if (c < k)
421    {
422      /* Skip line */
423      while (getc(fd) != '\n') {};
424      if (i)
425      {
426        i=0;
427        k=key[0];
428      }
429    }
430    else if (c == k)
431    {
432      i++;
433      if (i == kl)
434      {
435        // \t must follow, otherwise only substring match
436        if (getc(fd) != '\t') goto Failure;
437
438        // Now we found an exact match
439        if (hentry->key != key) strcpy(hentry->key, key);
440        // get node
441        i = 0;
442        while ((c = getc(fd)) != '\t' && c != EOF)
443        {
444          hentry->node[i] = c;
445          i++;
446        }
447        if (c == EOF) goto Failure;
448
449        // get url
450        hentry->node[i] = '\0';
451        i = 0;
452        while ((c = getc(fd)) != '\t' && c != EOF)
453        {
454          hentry->url[i] = c;
455          i++;
456        }
457        if (c == EOF) goto Failure;
458
459        // get chksum
460        hentry->url[i] = '\0';
461
462        if (fscanf(fd, "%ld\n", &(hentry->chksum)) != 1)
463        {
464          hentry->chksum = -1;
465        }
466        fclose(fd);
467        return TRUE;
468      }
469      else if (i > kl)
470      {
471        goto Failure;
472      }
473      else
474      {
475        k = key[i];
476      }
477    }
478    else
479    {
480      goto Failure;
481    }
482  }
483  Failure:
484  fclose(fd);
485  return FALSE;
486}
487
488// return TRUE if s matches re
489// FALSE, otherwise
490// does not distinguish lower and upper cases
491// inteprets * as wildcard
492static BOOLEAN strmatch(char* s, char* re)
493{
494  if (s == NULL || *s == '\0')
495    return (re == NULL || *re == '\0' || strcmp(re, "*") == 0);
496  if (re == NULL || *re == '\0') return FALSE;
497
498  int i;
499  char ls[MAX_HE_ENTRY_LENGTH + 1];
500  char rs[MAX_HE_ENTRY_LENGTH + 1];
501  char *l, *r, *ll, *rr;
502
503  // make everything to lower case
504  i=1;
505  ls[0] = '\0';
506  do
507  {
508    if (*s >= 'A' && *s <= 'Z') ls[i] = *s + ('a' - 'A');
509    else ls[i] = *s;
510    i++;
511    s++;
512  } while (*s != '\0');
513  ls[i] = '\0';
514  l = &(ls[1]);
515
516  i=1;
517  rs[0] = '\0';
518  do
519  {
520    if (*re >= 'A' && *re <= 'Z') rs[i]= *re + ('a' - 'A');
521    else rs[i] = *re;
522    i++;
523    re++;
524  } while (*re != '\0');
525  rs[i] = '\0';
526  r = &(rs[1]);
527
528  // chopp of exact matches from beginning and end
529  while (*r != '*' && *r != '\0' && *l != '\0')
530  {
531    if (*r != *l) return FALSE;
532    *r = '\0';
533    *s = '\0';
534    r++;
535    l++;
536  }
537  if (*r == '\0') return (*l == '\0');
538  if (*r == '*' && r[1] == '\0') return TRUE;
539  if (*l == '\0') return FALSE;
540
541  rr = &r[strlen(r) - 1];
542  ll = &l[strlen(l) - 1];
543  while (*rr != '*' && *rr != '\0' && *ll != '\0')
544  {
545    if (*rr != *ll) return FALSE;
546    *rr = '\0';
547    *ll = '\0';
548    rr--;
549    ll--;
550  }
551  if (*rr == '\0') return (*ll == '\0');
552  if (*rr == '*' && rr[-1] == '\0') return TRUE;
553  if (*ll == '\0') return FALSE;
554
555  // now *r starts with a * and ends with a *
556  r++;
557  *rr = '\0'; rr--;
558  while (*r != '\0')
559  {
560    rr = r + 1;
561    while (*rr != '*' && *rr != '\0') rr++;
562    if (*rr == '*')
563    {
564      *rr = '\0';
565      rr++;
566    }
567    l = strstr(l, r);
568    if (l == NULL) return FALSE;
569    r = rr;
570  }
571  return TRUE;
572}
573
574// similar to heKey2Entry, except that
575// key is taken as regexp (see above)
576// and number of matches is returned
577// if number of matches > 0, then hentry contains entry for first match
578// if number of matches > 1, matches are printed as komma-separated
579// into global string
580static int heReKey2Entry (char* filename, char* key, heEntry hentry)
581{
582  int i = 0;
583  FILE* fd;
584  char index_key[MAX_HE_ENTRY_LENGTH];
585
586  if (filename == NULL || key == NULL)  return 0;
587  fd = fopen(filename, "r");
588  if (fd == NULL) return 0;
589  while (fscanf(fd, "%[^\t]\t%*[^\n]\n", index_key) == 1)
590  {
591    if (strmatch(index_key, key))
592    {
593      i++;
594      if (i == 1)
595      {
596        heKey2Entry(filename, index_key, hentry);
597      }
598      else if (i == 2)
599      {
600        StringAppend("?%s; ?%s;", hentry->key, index_key);
601      }
602      else
603      {
604        StringAppend(" ?%s;", index_key);
605      }
606    }
607  }
608  fclose(fd);
609  return i;
610}
611
612// try to find the help string as a loaded procedure or library
613// if found, display the help and return TRUE
614// otherwise, return FALSE
615static BOOLEAN heOnlineHelp(char* s)
616{
617#ifdef HAVE_NAMESPACES
618  idhdl h, ns;
619  iiname2hdl(s, &ns, &h);
620#else /* HAVE_NAMESPACES */
621  idhdl h=idroot->get(s,myynest);
622#endif /* HAVE_NAMESPACES */
623
624  // try help for a procedure
625  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
626  {
627    char *lib=iiGetLibName(IDPROC(h));
628    if((lib!=NULL)&&(*lib!='\0'))
629    {
630      Print("// proc %s from lib %s\n",s,lib);
631      s=iiGetLibProcBuffer(IDPROC(h), 0);
632      if (s!=NULL)
633      {
634        PrintS(s);
635        omFree((ADDRESS)s);
636      }
637      return TRUE;
638    }
639    return FALSE;
640  }
641
642  // try help for a library
643  int ls = strlen(s);
644  char* str = NULL;
645  // check that it ends with "[.,_]lib"
646  if (strlen(s) >=4 &&  strcmp(&s[ls-3], "lib") == 0)
647  {
648    if (s[ls - 4] == '.') str = s;
649    else
650    {
651      str = omStrDup(s);
652      str[ls - 4] = '.';
653    }
654  }
655  else
656  {
657    return FALSE;
658  }
659
660  char libnamebuf[128];
661  FILE *fp=NULL;
662  // first, search for library of that name in LIB string
663  if ((str[1]!='\0') &&
664      ((iiLocateLib(str, libnamebuf) && (fp=feFopen(libnamebuf, "rb")) !=NULL)
665       ||
666       ((fp=feFopen(str,"rb", libnamebuf))!=NULL)))
667  {
668    extern FILE *yylpin;
669    lib_style_types lib_style; // = OLD_LIBSTYLE;
670
671    yylpin = fp;
672#ifdef HAVE_NAMESPACES
673    yylplex(str, libnamebuf, &lib_style, IDROOT, FALSE, GET_INFO);
674#else /* HAVE_NAMESPACES */
675    yylplex(str, libnamebuf, &lib_style, GET_INFO);
676#endif /* HAVE_NAMESPACES */
677    reinit_yylp();
678    if(lib_style == OLD_LIBSTYLE)
679    {
680      char buf[256];
681      fseek(fp, 0, SEEK_SET);
682      Warn( "library %s has an old format. Please fix it for the next time",
683            str);
684      if (str != s) omFree(str);
685      BOOLEAN found=FALSE;
686      while (fgets( buf, sizeof(buf), fp))
687      {
688        if (strncmp(buf,"//",2)==0)
689        {
690          if (found) return TRUE;
691        }
692        else if ((strncmp(buf,"proc ",5)==0)||(strncmp(buf,"LIB ",4)==0))
693        {
694          if (!found) WarnS("no help part in library found");
695          return TRUE;
696        }
697        else
698        {
699          found=TRUE;
700          PrintS(buf);
701        }
702      }
703    }
704    else
705    {
706      if (str != s) omFree(str);
707      fclose( yylpin );
708      PrintS(text_buffer);
709      omFree(text_buffer);
710      text_buffer=NULL;
711    }
712    return TRUE;
713  }
714
715  if (str != s) omFree(str);
716  return FALSE;
717}
718
719static long heKeyChksum(char* key)
720{
721  if (key == NULL || *key == '\0') return 0;
722#ifdef HAVE_NAMESPACES
723  idhdl h, ns;
724  iiname2hdl(key, &ns, &h);
725#else /* HAVE_NAMESPACES */
726  idhdl h=idroot->get(key,myynest);
727#endif /* HAVE_NAMESPACES */
728  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
729  {
730    procinfo *pi = IDPROC(h);
731    if (pi != NULL) return pi->data.s.help_chksum;
732  }
733  return 0;
734}
735
736/*****************************************************************
737 *
738 * Implementation : Help Browsers
739 *
740 *****************************************************************/
741
742static BOOLEAN feHelpCalled = FALSE;
743
744static void heBrowserHelp(heEntry hentry)
745{
746  // check checksums of procs
747  int kchksum = (hentry != NULL && hentry->chksum > 0 ?
748                 heKeyChksum(hentry->key) : 0);
749  if (kchksum  && kchksum != hentry->chksum && heOnlineHelp(hentry->key))
750    return;
751
752  if (heCurrentHelpBrowser == NULL) feHelpBrowser(NULL, 0);
753  assume(heCurrentHelpBrowser != NULL);
754  if (! feHelpCalled)
755  {
756    Warn("Displaying help in browser '%s'.", heCurrentHelpBrowser->browser);
757    if (strcmp(heCurrentHelpBrowser->browser, "netscape") == 0 &&
758        feResource('h', 0) == NULL)
759    {
760      Warn("Using URL '%s'.", feResource('u', 0));
761    }
762    Warn("Use 'system(\"--browser\", <browser>);' to change browser,");
763    char* browsers = StringSetS("where <browser> can be: ");
764    int i = 0;
765    i = 0;
766    while (heHelpBrowsers[i].browser != NULL)
767    {
768      if (heHelpBrowsers[i].init_proc(0,i))
769        StringAppend("\"%s\", ", heHelpBrowsers[i].browser);
770      i++;
771    }
772    if (browsers[strlen(browsers)-2] == ',')
773    {
774      browsers[strlen(browsers)-2] = '.';
775      browsers[strlen(browsers)-1] = '\0';
776    }
777    WarnS(browsers);
778  }
779
780  heCurrentHelpBrowser->help_proc(hentry, heCurrentHelpBrowserIndex);
781  feHelpCalled = TRUE;
782}
783
784#define MAX_SYSCMD_LEN MAXPATHLEN*2
785static BOOLEAN heGenInit(int warn, int br)
786{
787  if (heHelpBrowsers[br].required==NULL) return TRUE;
788  char *p=heHelpBrowsers[br].required;
789  while (*p>'\0')
790  {
791    switch (*p)
792    {
793      case '#': break;
794      case ' ': break;
795      case 'i': /* singular.hlp */
796      case 'x': /* singular.idx */
797      case 'h': /* html dir */
798               if (feResource(*p, warn) == NULL)
799               {
800                 if (warn) Warn("ressource `%c` not found",*p);
801                 return FALSE;
802               }
803               break;
804      case 'D': /* DISPLAY */
805               if (getenv("DISPLAY") == NULL)
806               {
807                 if (warn) WarnS("ressource `D` not found");
808                 return FALSE;
809               }
810               break;
811      case 'E': /* executable: E:xterm: */
812               {
813                 char name[128];
814                 char exec[128];
815                 memset(name,0,128);
816                 int i=0;
817                 p++;
818                 while (((*p==':')||(*p<=' ')) && (*p!='\0')) p++;
819                 while((i<127) && (*p>' ') && (*p!=':'))
820                 {
821                   name[i]=*p; p++; i++;
822                 }
823                 if (i==0) return FALSE;
824                 if (omFindExec(name,exec)==NULL)
825                 {
826                   if (warn) Warn("executable `%s` not found",name);
827                   return FALSE;
828                 }
829               }
830               break;
831      default: Warn("unknown char %c",*p);
832               break;
833    }
834    p++;
835  }
836  return TRUE;
837}
838
839static void heGenHelp(heEntry hentry, int br)
840{
841  char sys[MAX_SYSCMD_LEN];
842  char url[MAXPATHLEN];
843  char *p=heHelpBrowsers[br].action;
844  if (p==NULL) {PrintS("no action ?\n"); return;}
845  memset(sys,0,MAX_SYSCMD_LEN);
846  int i=0;
847  while ((*p>'\0')&& (i<MAX_SYSCMD_LEN))
848  {
849    if ((*p)=='%')
850    {
851      p++;
852      switch (*p)
853      {
854        case 'f': /* local html:file */
855        case 'h': /* local html:URL */
856        case 'H': /* www html */
857                 {
858                   char temp[256];
859                   char *htmldir = feResource('h' /*"HtmlDir"*/);
860                   if ((*p=='h')&&(htmldir!=NULL))
861                     strcat(sys,"file://localhost");
862                   else if ((*p=='H')||(htmldir==NULL))
863                     htmldir = feResource('u' /* %H -> "ManualUrl"*/);
864                     /* always defined */
865                   if (hentry != NULL && *(hentry->url) != '\0')
866                   #ifdef HAVE_VSNPRINTF
867                     snprintf(temp,256,"%s/%s", htmldir, hentry->url);
868                   else
869                     snprintf(temp,256,"%s/index.htm", htmldir);
870                   #else
871                     sprintf(temp,"%s/%s", htmldir, hentry->url);
872                   else
873                     sprintf(temp,"%s/index.htm", htmldir);
874                   #endif
875                   strcat(sys,temp);
876                   if ((*p)=='f')
877                   { // remove #SEC
878                     char *pp=strchr(sys,'#');
879                     if (pp!=NULL)
880                     { 
881                       *pp='\0';
882                       i=strlen(sys);
883                       memset(pp,0,MAX_SYSCMD_LEN-i);
884                     } 
885                   }
886                   i=strlen(sys);
887                   break;
888                 }
889        case 'i': /* singular.hlp */
890                 {
891                   char *i_res=feResource('i');
892                   if (i_res!=NULL) strcat(sys,i_res);
893                   else
894                   {
895                     WarnS("singular.hlp not found");
896                     return;
897                   }
898                   i=strlen(sys);
899                   break;
900                 }
901        case 'n': /* info node */
902                 {
903                   char temp[256];
904                   if ((hentry!=NULL) && (*(hentry->node) != '\0'))
905                     sprintf(temp,"%s",hentry->node);
906                   //else if ((hentry!=NULL) && (hentry->key!=NULL))
907                   //  sprintf(temp,"Index '%s'",hentry->key);
908                   else
909                     sprintf(temp,"Top");
910                   strcat(sys,temp);
911                   i=strlen(sys);
912                   break;
913                 }
914        default: break;
915      }
916      p++;
917    }
918    else
919    {
920      sys[i]=*p;
921      p++;i++;
922    }
923  }
924  Print("running `%s`\n",sys);
925  system(sys);
926}
927
928#ifdef ix86_Win
929static void heHtmlHelp(heEntry hentry)
930{
931  char url[MAXPATHLEN];
932  char* html_dir = feResource('h' /*"HtmlDir"*/);
933  sprintf(url, "%s/%s",
934          (html_dir != NULL ? html_dir : feResource('u' /*"ManualUrl"*/)),
935          (hentry!=NULL && *(hentry->url)!='\0' ? hentry->url : "index.htm"));
936
937  heOpenWinntUrl(url, (html_dir != NULL ? 1 : 0));
938}
939
940static void heWinHelp(heEntry hentry)
941{
942  char keyw[MAX_HE_ENTRY_LENGTH];
943  if ((hentry!=NULL)&&(hentry->key!=NULL))
944    strcpy(keyw,hentry->key);
945  else
946    strcpy(keyw," ");
947  char* helppath = feResource('h' /*"HtmlDir"*/);
948  const char *filename="/Manual.hlp";
949  int helppath_len=0;
950  if (helppath!=NULL) helppath_len=strlen(helppath);
951  char *callpath=(char *)omAlloc0(helppath_len+strlen(filename)+1);
952  if ((helppath!=NULL) && (*helppath>' '))
953    strcpy(callpath,helppath);
954  strcat(callpath,filename);
955  heOpenWinntHlp(keyw,callpath);
956  omfree(callpath);
957}
958#endif
959
960static BOOLEAN heDummyInit(int warn, int br)
961{
962  return TRUE;
963}
964static void heDummyHelp(heEntry hentry, int br)
965{
966  Werror("No functioning help browser available.");
967}
968
969static BOOLEAN heEmacsInit(int warn, int br)
970{
971  return TRUE;
972}
973static void heEmacsHelp(heEntry hentry, int br)
974{
975  WarnS("Your help command could not be executed. Use");
976  Warn("C-h C-s %s",
977       (hentry != NULL && *(hentry->node) != '\0' ? hentry->node : "Top"));
978  Warn("to enter the Singular online help. For general");
979  Warn("information on Singular running under Emacs, type C-h m.");
980}
981static int singular_manual(char *str);
982static void heBuiltinHelp(heEntry hentry, int br)
983{
984  char* node = omStrDup(hentry != NULL && *(hentry->node) != '\0' ?
985                       hentry->node : "Top");
986  singular_manual(node);
987  omFree(node);
988}
989
990
991/* ========================================================================== */
992// old, stupid builtin_help
993// This could be implemented much more clever, but I'm too lazy to do this now
994//
995#define HELP_OK        0
996#define FIN_INDEX    '\037'
997#define HELP_NOT_OPEN  1
998#define HELP_NOT_FOUND 2
999#define BUF_LEN        256
1000#define IDX_LEN        64
1001#define MAX_LINES      21
1002
1003static inline char tolow(char p)
1004{
1005  if (('A'<=p)&&(p<='Z')) return p | 040;
1006  return p;
1007}
1008
1009/*************************************************/
1010static int show(unsigned long offset,FILE *help, char *close)
1011{ char buffer[BUF_LEN+1];
1012  int  lines = 0;
1013
1014  if( help== NULL)
1015    if( (help = fopen(feResource('i'), "rb")) == NULL)
1016      return HELP_NOT_OPEN;
1017
1018  fseek(help,  (long)(offset+1), (int)0);
1019  while( !feof(help)
1020        && *fgets(buffer, BUF_LEN, help) != EOF
1021        && buffer[0] != FIN_INDEX)
1022  {
1023    printf("%s", buffer);
1024    if(lines++> MAX_LINES)
1025    {
1026      printf("\n Press <RETURN> to continue or x to exit help.\n");
1027      fflush(stdout);
1028      *close = (char)getchar();
1029      if(*close=='x')
1030      {
1031        getchar();
1032        break;
1033      }
1034      lines=0;
1035    }
1036  }
1037  if(*close!='x')
1038  {
1039    printf("\nEnd of part. Press <RETURN> to continue or x to exit help.\n");
1040    fflush(stdout);
1041    *close = (char)getchar();
1042    if(*close=='x')
1043      getchar();
1044  }
1045  return HELP_OK;
1046}
1047
1048/*************************************************/
1049static int singular_manual(char *str)
1050{ FILE *index=NULL,*help=NULL;
1051  unsigned long offset;
1052  char *p,close;
1053  int done = 0;
1054  char buffer[BUF_LEN+1],
1055       Index[IDX_LEN+1],
1056       String[IDX_LEN+1];
1057
1058  if( (index = fopen(feResource('i'), "rb")) == NULL)
1059  {
1060    return HELP_NOT_OPEN;
1061  }
1062
1063  for(p=str; *p; p++) *p = tolow(*p);/* */
1064  do
1065  {
1066    p--;
1067  }
1068  while ((p != str) && (*p<=' '));
1069  p++;
1070  *p='\0';
1071  (void)sprintf(String, " %s ", str);
1072
1073  while(!feof(index)
1074        && fgets(buffer, BUF_LEN, index) != (char *)0
1075        && buffer[0] != FIN_INDEX);
1076
1077  while(!feof(index))
1078  {
1079    (void)fgets(buffer, BUF_LEN, index); /* */
1080    (void)sscanf(buffer, "Node:%[^\177]\177%ld\n", Index, &offset);
1081    for(p=Index; *p; p++) *p = tolow(*p);/* */
1082    (void)strcat(Index, " ");
1083    if( strstr(Index, String)!=NULL)
1084    {
1085      done++; (void)show(offset, help, &close);
1086    }
1087    Index[0]='\0';
1088    if(close=='x')
1089    break;
1090  }
1091  if (index != NULL) (void)fclose(index);
1092  if (help != NULL) (void)fclose(help);
1093  if(! done)
1094  {
1095    Warn("`%s` not found",String);
1096    return HELP_NOT_FOUND;
1097  }
1098  return HELP_OK;
1099}
1100/*************************************************/
Note: See TracBrowser for help on using the repository browser.