source: git/Singular/fehelp.cc @ 698457

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