source: git/Singular/fehelp.cc @ 01fdf5

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