source: git/Singular/fehelp.cc @ de7793

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