source: git/Singular/fehelp.cc @ 09ab91d

fieker-DuValspielwiese
Last change on this file since 09ab91d was 11b447, checked in by Hans Schönemann <hannes@…>, 25 years ago
*hannes: added comments git-svn-id: file:///usr/local/Singular/svn/trunk@3420 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 23.8 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  Print("chksum for %s:procinfo:%d, idx:%d\n",hentry->key, kchksum,hentry->chksum);
637  if (kchksum  && kchksum != hentry->chksum && heOnlineHelp(hentry->key))
638    return;
639
640  if (heCurrentHelpBrowser == NULL) feHelpBrowser();
641  assume(heCurrentHelpBrowser != NULL);
642  Warn("Displaying help in browser '%s'.", heCurrentHelpBrowser->browser);
643  Warn("Use 'system(\"--browser\", \"<browser>\");' to change browser");
644  Warn("Use 'system(\"browsers\");'               for available browsers");
645  heCurrentHelpBrowser->help_proc(hentry);
646}
647
648#define MAX_SYSCMD_LEN MAXPATHLEN*2
649// browser functions
650static BOOLEAN heInfoInit(int warn)
651{
652  if (feResource('i', warn) == NULL)
653  {
654    if (warn) WarnS("'info' help browser not available: no InfoFile");
655    return FALSE;
656  }
657  if (feResource('I') == NULL)
658  {
659    if (warn)
660      WarnS("'info' help browser not available: no 'info' program found");
661    return FALSE;
662  }
663  return TRUE;
664}
665static void heInfoHelp(heEntry hentry)
666{
667  char sys[MAX_SYSCMD_LEN];
668
669  if (hentry != NULL && *(hentry->key) != '\0')
670  {
671    if (*(hentry->node) != '\0')
672      sprintf(sys, "%s -f %s --node='%s'",
673              feResource('I'), feResource('i'), hentry->node);
674    else
675      sprintf(sys, "%s -f %s Index '%s'",
676              feResource('I'), feResource('i'), hentry->key);
677  }
678  else
679    sprintf(sys, "%s -f %s --node=Top", feResource('I'), feResource('i'));
680  system(sys);
681}
682
683#if ! defined(WINNT) && ! defined(macintosh)
684static BOOLEAN heNetscapeInit(int warn)
685{
686  if (feResource('N' /*"netscape"*/, warn) == NULL)
687  {
688    if (warn) WarnS("'netscape' help browser not available: no 'netscape' program found");
689    return FALSE;
690  }
691  if (getenv("DISPLAY") == NULL)
692  {
693    if (warn) WarnS("'netscape' help browser not available:");
694    if (warn) WarnS("Environment variable DISPLAY not set");
695    return FALSE;
696  }
697
698  if (feResource('h' /*"HtmlDir"*/, warn) == NULL)
699  {
700    if (warn) WarnS("no local HtmlDir found");
701    if (warn) Warn("using %s instead", feResource('u' /*"ManualUrl"*/, warn));
702  }
703  return TRUE;
704}
705static void heNetscapeHelp(heEntry hentry)
706{
707  char sys[MAX_SYSCMD_LEN];
708  char url[MAXPATHLEN];
709  char* htmldir = feResource('h' /*"HtmlDir"*/);
710  char* urltype;
711
712  if (htmldir == NULL)
713  {
714    urltype = "";
715    htmldir = feResource('u' /*"ManualUrl"*/);
716  }
717  else
718  {
719    urltype = "file:";
720  }
721
722  if (hentry != NULL && *(hentry->url) != '\0')
723  {
724    sprintf(url, "%s%s/%s", urltype, htmldir, hentry->url);
725  }
726  else
727  {
728    sprintf(url, "%s%s/index.htm", urltype, htmldir);
729  }
730  sprintf(sys, "%s --remote 'OpenUrl(%s)' > /dev/null 2>&1",
731          feResource('N' /*"netscape"*/), url);
732
733  // --remote exits with status != 0 if netscaep isn't already running
734  if (system(sys) != 0)
735  {
736    sprintf(sys, "%s %s &", feResource('N' /*"netscape"*/), url);
737    system(sys);
738  }
739}
740
741static BOOLEAN heXinfoInit(int warn)
742{
743  if (getenv("DISPLAY") == NULL)
744  {
745    if (warn) WarnS("'xinfo' help browser not available:");
746    if (warn) WarnS("Environment variable DISPLAY not set");
747    return FALSE;
748  }
749  if (feResource('i', warn) == NULL)
750  {
751    if (warn) WarnS("'xinfo' help browser not available: no InfoFile");
752    return FALSE;
753  }
754  if (feResource('I', warn) == NULL)
755  {
756    if (warn) WarnS("'xinfo' help browser not available: no 'info' program found");
757    return FALSE;
758  }
759  if (feResource('X', warn) == NULL)
760  {
761    if (warn) WarnS("'xinfo' help browser not available: no 'xterm' program found");
762    return FALSE;
763  }
764  return TRUE;
765}
766static void heXinfoHelp(heEntry hentry)
767{
768  char sys[MAX_SYSCMD_LEN];
769
770  if (hentry != NULL && *(hentry->key) != '\0')
771  {
772    if (*(hentry->node) != '\0')
773      sprintf(sys, "%s -e %s -f %s --node='%s' &",
774              feResource('X'), feResource('I'), feResource('i'), hentry->node);
775    else
776      sprintf(sys, "%s -e %s -f %s Index '%s' &",
777              feResource('X'), feResource('I'), feResource('i'), hentry->key);
778  }
779  else
780    sprintf(sys, "%s -e %s -f %s --node=Top &",
781            feResource('X'), feResource('I'), feResource('i'));
782  system(sys);
783}
784
785static BOOLEAN heTkinfoInit(int warn)
786{
787  if (getenv("DISPLAY") == NULL)
788  {
789    if (warn) WarnS("'tkinfo' help browser not available:");
790    if (warn) WarnS("Environment variable DISPLAY not set");
791    return FALSE;
792  }
793  if (feResource('i', warn) == NULL)
794  {
795    if (warn) WarnS("'tkinfo' help browser not available: no InfoFile");
796    return FALSE;
797  }
798  if (feResource('T', warn) == NULL)
799  {
800    if (warn) WarnS("'tkinfo' help browser not available: no 'tkinfo' program found");
801    return FALSE;
802  }
803  return TRUE;
804}
805static void heTkinfoHelp(heEntry hentry)
806{
807  char sys[MAX_SYSCMD_LEN];
808  if (hentry != NULL && *(hentry->node) != '\0')
809  {
810    sprintf(sys, "%s '(%s)%s' &",
811            feResource('T'), feResource('i'), hentry->node);
812  }
813  else
814  {
815    sprintf(sys, "%s %s &",
816            feResource('T'), feResource('i'));
817  }
818  system(sys);
819}
820#endif // ! defined(WINNT) && ! defined(macintosh)
821
822static BOOLEAN heDummyInit(int warn)
823{
824  return TRUE;
825}
826static void heDummyHelp(heEntry hentry)
827{
828  Werror("No functioning help browser available.");
829}
830
831static BOOLEAN heEmacsInit(int warn)
832{
833  return TRUE;
834}
835static void heEmacsHelp(heEntry hentry)
836{
837  WarnS("Your help command could not be executed. Use");
838  Warn("C-h C-s %s",
839       (hentry != NULL && *(hentry->node) != '\0' ? hentry->node : "Top"));
840  Warn("to enter the Singular online help. For general");
841  Warn("information on Singular running under Emacs, type C-h m");
842}
843static BOOLEAN heBuiltinInit(int warn)
844{
845  if (feResource('i', warn) == NULL)
846  {
847    if (warn) WarnS("'builtin' help browser not available: no InfoFile");
848    return FALSE;
849  }
850  return TRUE;
851}
852static int singular_manual(char *str);
853static void heBuiltinHelp(heEntry hentry)
854{
855  char* node = mstrdup(hentry != NULL && *(hentry->node) != '\0' ?
856                       hentry->node : "Top");
857  singular_manual(node);
858  FreeL(node);
859}
860
861
862/* ========================================================================== */
863// old, stupid builtin_help
864// This could be implemented much more clever, but I'm too lazy to do this now
865//
866#define HELP_OK        0
867#define FIN_INDEX    '\037'
868#define not  !
869#define HELP_NOT_OPEN  1
870#define HELP_NOT_FOUND 2
871#define BUF_LEN        256
872#define IDX_LEN        64
873#define MAX_LINES      21
874
875#ifdef macintosh
876static char tolow(char p)
877#else
878static inline char tolow(char p)
879#endif
880{
881  if (('A'<=p)&&(p<='Z')) return p | 040;
882  return p;
883}
884
885/*************************************************/
886static int show(unsigned long offset,FILE *help, char *close)
887{ char buffer[BUF_LEN+1];
888  int  lines = 0;
889
890  if( help== NULL)
891    if( (help = fopen(feResource('i'), "rb")) == NULL)
892      return HELP_NOT_OPEN;
893
894  fseek(help,  (long)(offset+1), (int)0);
895  while( !feof(help)
896        && *fgets(buffer, BUF_LEN, help) != EOF
897        && buffer[0] != FIN_INDEX)
898  {
899    printf("%s", buffer);
900    if(lines++> MAX_LINES)
901    {
902#ifdef macintosh
903      printf("\n Press <RETURN> to continue or x and <RETURN> to exit help.\n");
904#else
905      printf("\n Press <RETURN> to continue or x to exit help.\n");
906#endif
907      fflush(stdout);
908      *close = (char)getchar();
909      if(*close=='x')
910      {
911        getchar();
912        break;
913      }
914      lines=0;
915    }
916  }
917  if(*close!='x')
918  {
919#ifdef macintosh
920    printf("\nEnd of part. Press <RETURN> to continue or x and <RETURN> to exit help.\n");
921#else
922    printf("\nEnd of part. Press <RETURN> to continue or x to exit help.\n");
923#endif
924    fflush(stdout);
925    *close = (char)getchar();
926    if(*close=='x')
927      getchar();
928  }
929  return HELP_OK;
930}
931
932/*************************************************/
933static int singular_manual(char *str)
934{ FILE *index=NULL,*help=NULL;
935  unsigned long offset;
936  char *p,close;
937  int done = 0;
938  char buffer[BUF_LEN+1],
939       Index[IDX_LEN+1],
940       String[IDX_LEN+1];
941
942  if( (index = fopen(feResource('i'), "rb")) == NULL)
943  {
944    return HELP_NOT_OPEN;
945  }
946
947  for(p=str; *p; p++) *p = tolow(*p);/* */
948  do
949  {
950    p--;
951  }
952  while ((p != str) && (*p<=' '));
953  p++;
954  *p='\0';
955  (void)sprintf(String, " %s ", str);
956
957  while(!feof(index)
958        && fgets(buffer, BUF_LEN, index) != (char *)0
959        && buffer[0] != FIN_INDEX);
960
961  while(!feof(index))
962  {
963    (void)fgets(buffer, BUF_LEN, index); /* */
964    (void)sscanf(buffer, "Node:%[^\177]\177%ld\n", Index, &offset);
965    for(p=Index; *p; p++) *p = tolow(*p);/* */
966    (void)strcat(Index, " ");
967    if( strstr(Index, String)!=NULL)
968    {
969      done++; (void)show(offset, help, &close);
970    }
971    Index[0]='\0';
972    if(close=='x')
973    break;
974  }
975  if (index != NULL) (void)fclose(index);
976  if (help != NULL) (void)fclose(help);
977  if(not done)
978  {
979    Warn("`%s` not found",String);
980    return HELP_NOT_FOUND;
981  }
982  return HELP_OK;
983}
984/*************************************************/
Note: See TracBrowser for help on using the repository browser.