source: git/Singular/fehelp.cc @ fdc537

spielwiese
Last change on this file since fdc537 was 2fdf64, checked in by Olaf Bachmann <obachman@…>, 24 years ago
minor changes git-svn-id: file:///usr/local/Singular/svn/trunk@4375 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 "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 *
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    feReportBug("");
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    if (feOptSpec[FE_OPT_BROWSER].value == NULL) 
276      FreeL(feOptSpec[FE_OPT_BROWSER].value);
277   feOptSpec[FE_OPT_BROWSER].value
278     = (void*) mstrdup(heCurrentHelpBrowser->browser);
279  }
280  return heCurrentHelpBrowser->browser;
281}
282
283void  feStringAppendBrowsers(int warn)
284{
285  int i;
286  StringAppendS("Available HelpBrowsers: ");
287
288  i = 0;
289  while (heHelpBrowsers[i].browser != NULL)
290  {
291    if (heHelpBrowsers[i].init_proc(warn))
292      StringAppend("%s, ", heHelpBrowsers[i].browser);
293    i++;
294  }
295  StringAppend("\nCurrent HelpBrowser: %s ", feHelpBrowser());
296}
297
298
299/*****************************************************************
300 *
301 * Implementation: local function
302 *
303 *****************************************************************/
304// Remove whitspaces from beginning and end, return NULL if only whitespaces
305static char* strclean(char* str)
306{
307  if (str == NULL) return NULL;
308  char *s=str;
309  while (*s <= ' ' && *s != '\0') s++;
310  if (*s == '\0') return NULL;
311  char *ss=s;
312  while (*ss!='\0') ss++;
313  ss--;
314  while (*ss <= ' ' && *ss != '\0')
315  {
316    *ss='\0';
317    ss--;
318  }
319  if (*ss == '\0') return NULL;
320  return s;
321}
322
323// Finds help entry for key:
324// returns filled-in hentry and TRUE, on success
325// FALSE, on failure
326// Assumes that lines of idx file have the following form
327// key\tnode\turl\tchksum\n (chksum ma be empty, then it is set to -1)
328// and that lines are sorted alpahbetically w.r.t. index entries
329static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry)
330{
331  FILE* fd;
332  char c, k;
333  int kl, i;
334  *(hentry->key) = '\0';
335  *(hentry->url) = '\0';
336  *(hentry->node) = '\0';
337  hentry->chksum = 0;
338  if (filename == NULL || key == NULL)  return FALSE;
339  fd = fopen(filename, "r");
340  if (fd == NULL) return FALSE;
341  kl = strlen(key);
342
343  k = key[0];
344  i = 0;
345  while ((c = getc(fd)) != EOF)
346  {
347    if (c < k)
348    {
349      /* Skip line */
350      while (getc(fd) != '\n') {};
351      if (i)
352      {
353        i=0;
354        k=key[0];
355      }
356    }
357    else if (c == k)
358    {
359      i++;
360      if (i == kl)
361      {
362        // \t must follow, otherwise only substring match
363        if (getc(fd) != '\t') goto Failure;
364
365        // Now we found an exact match
366        if (hentry->key != key) strcpy(hentry->key, key);
367        // get node
368        i = 0;
369        while ((c = getc(fd)) != '\t' && c != EOF)
370        {
371          hentry->node[i] = c;
372          i++;
373        }
374        if (c == EOF) goto Failure;
375
376        // get url
377        hentry->node[i] = '\0';
378        i = 0;
379        while ((c = getc(fd)) != '\t' && c != EOF)
380        {
381          hentry->url[i] = c;
382          i++;
383        }
384        if (c == EOF) goto Failure;
385
386        // get chksum
387        hentry->url[i] = '\0';
388
389        if (fscanf(fd, "%ld\n", &(hentry->chksum)) != 1)
390        {
391          hentry->chksum = -1;
392        }
393        fclose(fd);
394        return TRUE;
395      }
396      else if (i > kl)
397      {
398        goto Failure;
399      }
400      else
401      {
402        k = key[i];
403      }
404    }
405    else
406    {
407      goto Failure;
408    }
409  }
410  Failure:
411  fclose(fd);
412  return FALSE;
413}
414
415// return TRUE if s matches re
416// FALSE, otherwise
417// does not distinguish lower and upper cases
418// inteprets * as wildcard
419static BOOLEAN strmatch(char* s, char* re)
420{
421  if (s == NULL || *s == '\0')
422    return (re == NULL || *re == '\0' || strcmp(re, "*") == 0);
423  if (re == NULL || *re == '\0') return FALSE;
424
425  int i;
426  char ls[MAX_HE_ENTRY_LENGTH + 1];
427  char rs[MAX_HE_ENTRY_LENGTH + 1];
428  char *l, *r, *ll, *rr;
429
430  // make everything to lower case
431  i=1;
432  ls[0] = '\0';
433  do
434  {
435    if (*s >= 'A' && *s <= 'Z') ls[i] = *s + ('a' - 'A');
436    else ls[i] = *s;
437    i++;
438    s++;
439  } while (*s != '\0');
440  ls[i] = '\0';
441  l = &(ls[1]);
442
443  i=1;
444  rs[0] = '\0';
445  do
446  {
447    if (*re >= 'A' && *re <= 'Z') rs[i]= *re + ('a' - 'A');
448    else rs[i] = *re;
449    i++;
450    re++;
451  } while (*re != '\0');
452  rs[i] = '\0';
453  r = &(rs[1]);
454
455  // chopp of exact matches from beginning and end
456  while (*r != '*' && *r != '\0' && *l != '\0')
457  {
458    if (*r != *l) return FALSE;
459    *r = '\0';
460    *s = '\0';
461    r++;
462    l++;
463  }
464  if (*r == '\0') return (*l == '\0');
465  if (*r == '*' && r[1] == '\0') return TRUE;
466  if (*l == '\0') return FALSE;
467
468  rr = &r[strlen(r) - 1];
469  ll = &l[strlen(l) - 1];
470  while (*rr != '*' && *rr != '\0' && *ll != '\0')
471  {
472    if (*rr != *ll) return FALSE;
473    *rr = '\0';
474    *ll = '\0';
475    rr--;
476    ll--;
477  }
478  if (*rr == '\0') return (*ll == '\0');
479  if (*rr == '*' && rr[-1] == '\0') return TRUE;
480  if (*ll == '\0') return FALSE;
481
482  // now *r starts with a * and ends with a *
483  r++;
484  *rr = '\0'; rr--;
485  while (*r != '\0')
486  {
487    rr = r + 1;
488    while (*rr != '*' && *rr != '\0') rr++;
489    if (*rr == '*')
490    {
491      *rr = '\0';
492      rr++;
493    }
494    l = strstr(l, r);
495    if (l == NULL) return FALSE;
496    r = rr;
497  }
498  return TRUE;
499}
500
501// similar to heKey2Entry, except that
502// key is taken as regexp (see above)
503// and number of matches is returned
504// if number of matches > 0, then hentry contains entry for first match
505// if number of matches > 1, matches are printed as komma-separated
506// into global string
507static int heReKey2Entry (char* filename, char* key, heEntry hentry)
508{
509  int i = 0;
510  FILE* fd;
511  char index_key[MAX_HE_ENTRY_LENGTH];
512
513  if (filename == NULL || key == NULL)  return 0;
514  fd = fopen(filename, "r");
515  if (fd == NULL) return 0;
516  while (fscanf(fd, "%[^\t]\t%*[^\n]\n", index_key) == 1)
517  {
518    if (strmatch(index_key, key))
519    {
520      i++;
521      if (i == 1)
522      {
523        heKey2Entry(filename, index_key, hentry);
524      }
525      else if (i == 2)
526      {
527        StringAppend("?%s; ?%s;", hentry->key, index_key);
528      }
529      else
530      {
531        StringAppend(" ?%s;", index_key);
532      }
533    }
534  }
535  fclose(fd);
536  return i;
537}
538
539// try to find the help string as a loaded procedure or library
540// if found, display the help and return TRUE
541// otherwise, return FALSE
542static BOOLEAN heOnlineHelp(char* s)
543{
544#ifdef HAVE_NAMESPACES
545  idhdl h, ns;
546  iiname2hdl(s, &ns, &h);
547#else /* HAVE_NAMESPACES */
548  idhdl h=idroot->get(s,myynest);
549#endif /* HAVE_NAMESPACES */
550
551  // try help for a procedure
552  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
553  {
554    char *lib=iiGetLibName(IDPROC(h));
555    if((lib!=NULL)&&(*lib!='\0'))
556    {
557      Print("// proc %s from lib %s\n",s,lib);
558      s=iiGetLibProcBuffer(IDPROC(h), 0);
559      if (s!=NULL)
560      {
561        PrintS(s);
562        FreeL((ADDRESS)s);
563      }
564      return TRUE;
565    }
566    return FALSE;
567  }
568
569  // try help for a library
570  int ls = strlen(s);
571  char* str = NULL;
572  // check that it ends with "[.,_]lib"
573  if (strlen(s) >=4 &&  strcmp(&s[ls-3], "lib") == 0)
574  {
575    if (s[ls - 4] == '.') str = s;
576    else
577    {
578      str = mstrdup(s);
579      str[ls - 4] = '.';
580    }
581  }
582  else
583  {
584    return FALSE;
585  }
586
587  char libnamebuf[128];
588  FILE *fp=NULL;
589  // first, search for library of that name in LIB string
590  if ((str[1]!='\0') && 
591      ((iiLocateLib(str, libnamebuf) && (fp=feFopen(libnamebuf, "rb")) !=NULL)
592       ||
593       ((fp=feFopen(str,"rb", libnamebuf))!=NULL)))
594  {
595    extern FILE *yylpin;
596    lib_style_types lib_style; // = OLD_LIBSTYLE;
597
598    yylpin = fp;
599#ifdef HAVE_NAMESPACES
600    yylplex(str, libnamebuf, &lib_style, IDROOT, FALSE, GET_INFO);
601#else /* HAVE_NAMESPACES */
602    yylplex(str, libnamebuf, &lib_style, GET_INFO);
603#endif /* HAVE_NAMESPACES */
604    reinit_yylp();
605    if(lib_style == OLD_LIBSTYLE)
606    {
607      char buf[256];
608      fseek(fp, 0, SEEK_SET);
609      Warn( "library %s has an old format. Please fix it for the next time",
610            str);
611      if (str != s) FreeL(str);
612      BOOLEAN found=FALSE;
613      while (fgets( buf, sizeof(buf), fp))
614      {
615        if (strncmp(buf,"//",2)==0)
616        {
617          if (found) return TRUE;
618        }
619        else if ((strncmp(buf,"proc ",5)==0)||(strncmp(buf,"LIB ",4)==0))
620        {
621          if (!found) WarnS("no help part in library found");
622          return TRUE;
623        }
624        else
625        {
626          found=TRUE;
627          PrintS(buf);
628        }
629      }
630    }
631    else
632    {
633      if (str != s) FreeL(str);
634      fclose( yylpin );
635      PrintS(text_buffer);
636      FreeL(text_buffer);
637      text_buffer=NULL;
638    }
639    return TRUE;
640  }
641
642  if (str != s) FreeL(str);
643  return FALSE;
644}
645
646static long heKeyChksum(char* key)
647{
648  if (key == NULL || *key == '\0') return 0;
649#ifdef HAVE_NAMESPACES
650  idhdl h, ns;
651  iiname2hdl(key, &ns, &h);
652#else /* HAVE_NAMESPACES */
653  idhdl h=idroot->get(key,myynest);
654#endif /* HAVE_NAMESPACES */
655  if ((h!=NULL) && (IDTYP(h)==PROC_CMD))
656  {
657    procinfo *pi = IDPROC(h);
658    if (pi != NULL) return pi->data.s.help_chksum;
659  }
660  return 0;
661}
662
663/*****************************************************************
664 *
665 * Implementation : Help Browsers
666 *
667 *****************************************************************/
668
669static BOOLEAN feHelpCalled = FALSE;
670
671static void heBrowserHelp(heEntry hentry)
672{
673  // check checksums of procs
674  int kchksum = (hentry != NULL && hentry->chksum > 0 ?
675                 heKeyChksum(hentry->key) : 0);
676  if (kchksum  && kchksum != hentry->chksum && heOnlineHelp(hentry->key))
677    return;
678
679  if (heCurrentHelpBrowser == NULL) feHelpBrowser(NULL, 0);
680  assume(heCurrentHelpBrowser != NULL);
681  if (! feHelpCalled)
682  {
683    Warn("Displaying help in browser '%s'.", heCurrentHelpBrowser->browser);
684    if (strcmp(heCurrentHelpBrowser->browser, "netscape") == 0 &&
685        feResource('h', 0) == NULL)
686    {
687      Warn("Using URL '%s'.", feResource('u', 0));
688    }
689    Warn("Use 'system(\"--browser\", <browser>);' to change browser,");
690    char* browsers = StringSetS("where <browser> can be: ");
691    int i = 0;
692    i = 0;
693    while (heHelpBrowsers[i].browser != NULL)
694    {
695      if (heHelpBrowsers[i].init_proc(0))
696        StringAppend("\"%s\", ", heHelpBrowsers[i].browser);
697      i++;
698    }
699    if (browsers[strlen(browsers)-2] == ',')
700    {
701      browsers[strlen(browsers)-2] = '.';
702      browsers[strlen(browsers)-1] = '\0';
703    }
704    WarnS(browsers);
705  }
706
707  heCurrentHelpBrowser->help_proc(hentry);
708  feHelpCalled = TRUE;
709}
710
711#define MAX_SYSCMD_LEN MAXPATHLEN*2
712// browser functions
713static BOOLEAN heInfoInit(int warn)
714{
715  if (feResource('i', warn) == NULL)
716  {
717    if (warn) WarnS("'info' help browser not available: no InfoFile");
718    return FALSE;
719  }
720  if (feResource('I') == NULL)
721  {
722    if (warn)
723      WarnS("'info' help browser not available: no 'info' program found");
724    return FALSE;
725  }
726  return TRUE;
727}
728static void heInfoHelp(heEntry hentry)
729{
730  char sys[MAX_SYSCMD_LEN];
731
732  if (hentry != NULL && *(hentry->key) != '\0')
733  {
734    if (*(hentry->node) != '\0')
735      sprintf(sys, "%s -f %s --node='%s'",
736              feResource('I'), feResource('i'), hentry->node);
737    else
738      sprintf(sys, "%s -f %s Index '%s'",
739              feResource('I'), feResource('i'), hentry->key);
740  }
741  else
742    sprintf(sys, "%s -f %s --node=Top", feResource('I'), feResource('i'));
743  system(sys);
744}
745
746#if ! defined(macintosh)
747static BOOLEAN heNetscapeInit(int warn)
748{
749  if (feResource('N' /*"netscape"*/, warn) == NULL)
750  {
751    if (warn) WarnS("'netscape' help browser not available: no 'netscape' program found");
752    return FALSE;
753  }
754#ifndef WINNT
755  if (getenv("DISPLAY") == NULL)
756  {
757    if (warn) WarnS("'netscape' help browser not available:");
758    if (warn) WarnS("Environment variable DISPLAY not set");
759    return FALSE;
760  }
761#endif
762 
763  if (feResource('h' /*"HtmlDir"*/, (feOptValue(FE_OPT_ALLOW_NET)? 0 : warn)) 
764      == NULL)
765  {
766    if (warn) WarnS("No local HtmlDir found.");
767    if (feOptValue(FE_OPT_ALLOW_NET))
768    {
769      if (warn) Warn("Using URL '%s' instead.", feResource('u' /*"ManualUrl"*/, warn));
770    }
771    else
772      return FALSE;
773  }
774  return TRUE;
775}
776
777static void heNetscapeHelp(heEntry hentry)
778{
779  char sys[MAX_SYSCMD_LEN];
780  char url[MAXPATHLEN];
781  char* htmldir = feResource('h' /*"HtmlDir"*/);
782  char* urltype;
783
784  if (htmldir == NULL)
785  {
786    urltype = "";
787    htmldir = feResource('u' /*"ManualUrl"*/);
788  }
789  else
790  {
791    urltype = "file:";
792  }
793
794  if (hentry != NULL && *(hentry->url) != '\0')
795  {
796    sprintf(url, "%s%s/%s", urltype, htmldir, hentry->url);
797  }
798  else
799  {
800    sprintf(url, "%s%s/index.htm", urltype, htmldir);
801  }
802#ifndef WINNT
803  sprintf(sys, "%s --remote 'OpenUrl(%s)' > /dev/null 2>&1",
804#else
805  sprintf(sys, "%s %s", 
806#endif
807          feResource('N' /*"netscape"*/), url);
808
809  // --remote exits with status != 0 if netscaep isn't already running
810  if (system(sys) != 0)
811  {
812    sprintf(sys, "%s %s &", feResource('N' /*"netscape"*/), url);
813    system(sys);
814  }
815  else
816  {
817    if (! feHelpCalled)
818    {
819      Warn("Help is displayed in already running 'netscape'.");
820    }
821  }
822}
823
824#ifdef WINNT
825static void heHtmlHelp(heEntry hentry)
826{
827  char url[MAXPATHLEN];
828  char* html_dir = feResource('h' /*"HtmlDir"*/);
829  sprintf(url, "%s/%s",
830          (html_dir != NULL ? html_dir : feResource('u' /*"ManualUrl"*/)),
831          (hentry!=NULL && *(hentry->url)!='\0' ? hentry->url : "index.htm"));
832
833  heOpenWinntUrl(url, (html_dir != NULL ? 1 : 0));
834}
835#endif
836
837static BOOLEAN heXinfoInit(int warn)
838{
839#ifndef WINNT
840  if (getenv("DISPLAY") == NULL)
841  {
842    if (warn) WarnS("'xinfo' help browser not available:");
843    if (warn) WarnS("Environment variable DISPLAY not set");
844    return FALSE;
845  }
846#endif
847  if (feResource('i', warn) == NULL)
848  {
849    if (warn) WarnS("'xinfo' help browser not available: no InfoFile");
850    return FALSE;
851  }
852  if (feResource('I', warn) == NULL)
853  {
854    if (warn) WarnS("'xinfo' help browser not available: no 'info' program found");
855    return FALSE;
856  }
857  if (feResource('X', warn) == NULL)
858  {
859    if (warn) WarnS("'xinfo' help browser not available: no 'xterm' program found");
860    return FALSE;
861  }
862  return TRUE;
863}
864static void heXinfoHelp(heEntry hentry)
865{
866  char sys[MAX_SYSCMD_LEN];
867
868#ifdef WINNT
869#define EXTRA_XTERM_ARGS "+vb -sb -fb Courier-bold-13 -tn linux -cr Red3"
870#else
871#define EXTRA_XTERM_ARGS ""
872#endif
873
874  if (hentry != NULL && *(hentry->key) != '\0')
875  {
876    if (*(hentry->node) != '\0')
877      sprintf(sys, "%s %s -e %s -f %s --node='%s' &",
878              feResource('X'), EXTRA_XTERM_ARGS, 
879              feResource('I'), feResource('i'), hentry->node);
880    else
881      sprintf(sys, "%s %s -e %s -f %s Index '%s' &",
882              feResource('X'), EXTRA_XTERM_ARGS,
883              feResource('I'), feResource('i'), hentry->key);
884  }
885  else
886    sprintf(sys, "%s %s -e %s -f %s --node=Top &",
887            feResource('X'), EXTRA_XTERM_ARGS,
888            feResource('I'), feResource('i'));
889  system(sys);
890}
891
892static BOOLEAN heTkinfoInit(int warn)
893{
894#ifndef WINNT
895  if (getenv("DISPLAY") == NULL)
896  {
897    if (warn) WarnS("'tkinfo' help browser not available:");
898    if (warn) WarnS("Environment variable DISPLAY not set");
899    return FALSE;
900  }
901#endif
902  if (feResource('i', warn) == NULL)
903  {
904    if (warn) WarnS("'tkinfo' help browser not available: no InfoFile");
905    return FALSE;
906  }
907  if (feResource('T', warn) == NULL)
908  {
909    if (warn) WarnS("'tkinfo' help browser not available: no 'tkinfo' program found");
910    return FALSE;
911  }
912  return TRUE;
913}
914static void heTkinfoHelp(heEntry hentry)
915{
916  char sys[MAX_SYSCMD_LEN];
917  if (hentry != NULL && *(hentry->node) != '\0')
918  {
919    sprintf(sys, "%s '(%s)%s' &",
920            feResource('T'), feResource('i'), hentry->node);
921  }
922  else
923  {
924    sprintf(sys, "%s %s &",
925            feResource('T'), feResource('i'));
926  }
927  system(sys);
928}
929#endif // ! defined(macintosh)
930
931static BOOLEAN heDummyInit(int warn)
932{
933  return TRUE;
934}
935static void heDummyHelp(heEntry hentry)
936{
937  Werror("No functioning help browser available.");
938}
939
940static BOOLEAN heEmacsInit(int warn)
941{
942  return TRUE;
943}
944static void heEmacsHelp(heEntry hentry)
945{
946  WarnS("Your help command could not be executed. Use");
947  Warn("C-h C-s %s",
948       (hentry != NULL && *(hentry->node) != '\0' ? hentry->node : "Top"));
949  Warn("to enter the Singular online help. For general");
950  Warn("information on Singular running under Emacs, type C-h m.");
951}
952static BOOLEAN heBuiltinInit(int warn)
953{
954  if (feResource('i', warn) == NULL)
955  {
956    if (warn) WarnS("'builtin' help browser not available: no InfoFile");
957    return FALSE;
958  }
959  return TRUE;
960}
961static int singular_manual(char *str);
962static void heBuiltinHelp(heEntry hentry)
963{
964  char* node = mstrdup(hentry != NULL && *(hentry->node) != '\0' ?
965                       hentry->node : "Top");
966  singular_manual(node);
967  FreeL(node);
968}
969
970
971/* ========================================================================== */
972// old, stupid builtin_help
973// This could be implemented much more clever, but I'm too lazy to do this now
974//
975#define HELP_OK        0
976#define FIN_INDEX    '\037'
977#define not  !
978#define HELP_NOT_OPEN  1
979#define HELP_NOT_FOUND 2
980#define BUF_LEN        256
981#define IDX_LEN        64
982#define MAX_LINES      21
983
984#ifdef macintosh
985static char tolow(char p)
986#else
987static inline char tolow(char p)
988#endif
989{
990  if (('A'<=p)&&(p<='Z')) return p | 040;
991  return p;
992}
993
994/*************************************************/
995static int show(unsigned long offset,FILE *help, char *close)
996{ char buffer[BUF_LEN+1];
997  int  lines = 0;
998
999  if( help== NULL)
1000    if( (help = fopen(feResource('i'), "rb")) == NULL)
1001      return HELP_NOT_OPEN;
1002
1003  fseek(help,  (long)(offset+1), (int)0);
1004  while( !feof(help)
1005        && *fgets(buffer, BUF_LEN, help) != EOF
1006        && buffer[0] != FIN_INDEX)
1007  {
1008    printf("%s", buffer);
1009    if(lines++> MAX_LINES)
1010    {
1011#ifdef macintosh
1012      printf("\n Press <RETURN> to continue or x and <RETURN> to exit help.\n");
1013#else
1014      printf("\n Press <RETURN> to continue or x to exit help.\n");
1015#endif
1016      fflush(stdout);
1017      *close = (char)getchar();
1018      if(*close=='x')
1019      {
1020        getchar();
1021        break;
1022      }
1023      lines=0;
1024    }
1025  }
1026  if(*close!='x')
1027  {
1028#ifdef macintosh
1029    printf("\nEnd of part. Press <RETURN> to continue or x and <RETURN> to exit help.\n");
1030#else
1031    printf("\nEnd of part. Press <RETURN> to continue or x to exit help.\n");
1032#endif
1033    fflush(stdout);
1034    *close = (char)getchar();
1035    if(*close=='x')
1036      getchar();
1037  }
1038  return HELP_OK;
1039}
1040
1041/*************************************************/
1042static int singular_manual(char *str)
1043{ FILE *index=NULL,*help=NULL;
1044  unsigned long offset;
1045  char *p,close;
1046  int done = 0;
1047  char buffer[BUF_LEN+1],
1048       Index[IDX_LEN+1],
1049       String[IDX_LEN+1];
1050
1051  if( (index = fopen(feResource('i'), "rb")) == NULL)
1052  {
1053    return HELP_NOT_OPEN;
1054  }
1055
1056  for(p=str; *p; p++) *p = tolow(*p);/* */
1057  do
1058  {
1059    p--;
1060  }
1061  while ((p != str) && (*p<=' '));
1062  p++;
1063  *p='\0';
1064  (void)sprintf(String, " %s ", str);
1065
1066  while(!feof(index)
1067        && fgets(buffer, BUF_LEN, index) != (char *)0
1068        && buffer[0] != FIN_INDEX);
1069
1070  while(!feof(index))
1071  {
1072    (void)fgets(buffer, BUF_LEN, index); /* */
1073    (void)sscanf(buffer, "Node:%[^\177]\177%ld\n", Index, &offset);
1074    for(p=Index; *p; p++) *p = tolow(*p);/* */
1075    (void)strcat(Index, " ");
1076    if( strstr(Index, String)!=NULL)
1077    {
1078      done++; (void)show(offset, help, &close);
1079    }
1080    Index[0]='\0';
1081    if(close=='x')
1082    break;
1083  }
1084  if (index != NULL) (void)fclose(index);
1085  if (help != NULL) (void)fclose(help);
1086  if(not done)
1087  {
1088    Warn("`%s` not found",String);
1089    return HELP_NOT_FOUND;
1090  }
1091  return HELP_OK;
1092}
1093/*************************************************/
Note: See TracBrowser for help on using the repository browser.